1.Lock 接口
锁用来控制多个线程访问共享资源方式,一个锁可以防止多个线程同时访问共享资源,在锁之前,依靠synchronized关键字来实现锁功能,在使用时需要显式获取和释放锁,但拥有锁获取和释放的可操作性,可中断的获取锁syn不具备的同步特性,利用syn控制锁时将会隐式获取锁,但是被固化了,Lock通常在finally中使用.
Lock与synchronized不具备的特性
特性 | 名称 |
尝试非阻塞的获取锁 | 尝试获取锁时,如果没有被其它线程获取到,这成功获取持有锁 |
能被中断获取锁 | 获取到锁的线程能够相应中断,当被中断时,中断异常抛出,锁释放 |
超时获取锁 | 在截至时间之前获取锁,则返回 |
2.队列同步器
队列同步器用来构建锁或者其他同步组件的基础框架,使用INT标识同步状态,通过FIFO队列来完成资源获取线程的排队工作。同步器的主要使用方式为继承,子类通过继承器同步实现抽象方法管理同步状态,通过使用同步器三个方法(getState().setState(int newState),compareAndSetState(int expect,int update))实现同步状态的更改,同步器本身没有实现任何同步接口,仅仅定义了同步状态获取和和释放的方法供同步组件使用,同步器是实现锁的关键,在锁中实现中聚合同步器,利用同步器实现锁的语义.
3.队列同步器实现
3.1同步队列
同步器依赖同步队列(FIFO)来实现同步状态管理,当线程同步获取失败时,同步器将当前线程构造成一个节点,并加入到队列中,同时阻塞当前线程,当同步状态释放时,会把首节点唤醒,并重新尝试获取同步状态,节点(NODE)是构成同步状态的基础,同步器拥有首节点和尾节点。
在同步器中包含两个节点类型,一个指向头,一个指向尾,同步器提供了一个基于CAS的设置尾节点方法:compareAndSetTail(Node expert,Node Update)来建立首尾关联.
同步队列遵循FIFO,首节点获取同步状态成功的节点,释放后重新唤醒后继节点,而后继节点将被作为首节点获取,通过首节点next引用进行关联.
4.重入锁
表示锁能够支持一个线程对资源的重复加锁,说还支持获取锁的公平和非公平性选择
在实现重入锁时需要考虑,线程再次获取锁以及释放的公平性,在公平与公平性的区别针对锁而言,如果一个锁是公平的,锁的获取顺序应该是FIFO,对于非公平锁,只要CAS设置同步状态成功,则表示当前线程获取到了锁.
5.读写锁
读写锁可以允许多个读线程访问,在写线程访问时,所有的RW线程将被阻塞,读写锁维护一对锁,通过分离RW锁使并发性相比排它锁有很大的提升
读写锁能够简化RW交互场景编程范式,在JAVA5之前,这些操作需要使用JAVA的等待通知机制,但是问题在于写操作开始时,所有晚于写操作均会进入等待状态,只有写完成通知之后,所有的读操作才会进行,这样可以保证读操作能够读取到正确的数据,不会出现脏读,而读写锁只需要在读时获取读锁,写操作获取写锁就行,在一般情况下,RW锁性能比排它锁好,能够提供更高的吞吐量,JAVA通过并发提供实现是ReentrantReadWriteLock,它具有以下特性
特性 | 描述 |
公平性选择 | 支持非公平(默认)和公平锁获取方式,吞吐量非公平优于公平 |
重进入 | 支持重进入 |
锁降级 | 写锁能够降级为读锁 |