您好,欢迎访问一九零五行业门户网

Java中的锁--同步锁和JUC包中的锁

这篇文章主要为大家详细介绍了java concurrency之锁的相关资料,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
根据锁的添加到java中的时间,java中的锁,可以分为同步锁和juc包中的锁。
同步锁
即通过synchronized关键字来进行同步,实现对竞争资源的互斥访问的锁。java 1.0版本中就已经支持同步锁了。
同步锁的原理是,对于每一个对象,有且仅有一个同步锁;不同的线程能共同访问该同步锁。但是,在同一个时间点,该同步锁能且只能被一个线程获取到。这样,获取到同步锁的线程就能进行cpu调度,从而在cpu上执行;而没有获取到同步锁的线程,必须进行等待,直到获取到同步锁之后才能继续运行。这就是,多线程通过同步锁进行同步的原理!
juc包中的锁
相比同步锁,juc包中的锁的功能更加强大,它为锁提供了一个框架,该框架允许更灵活地使用锁,只是它的用法更难罢了。
juc包中的锁,包括:lock接口,readwritelock接口,locksupport阻塞原语,condition条件,abstractownablesynchronizer/abstractqueuedsynchronizer/abstractqueuedlongsynchronizer三个抽象类,reentrantlock独占锁,reentrantreadwritelock读写锁。由于countdownlatch,cyclicbarrier和semaphore也是通过aqs来实现的;因此,我也将它们归纳到锁的框架中进行介绍。
先看看锁的框架图,如下所示。
01. lock接口
juc包中的 lock 接口支持那些语义不同(重入、公平等)的锁规则。所谓语义不同,是指锁可是有公平机制的锁、非公平机制的锁、可重入的锁等等。公平机制是指不同线程获取锁的机制是公平的,而非公平机制则是指不同线程获取锁的机制是非公平的,可重入的锁是指同一个锁能够被一个线程多次获取。
02. readwritelock
readwritelock 接口以和lock类似的方式定义了一些读取者可以共享而写入者独占的锁。juc包只有一个类实现了该接口,即 reentrantreadwritelock,因为它适用于大部分的标准用法上下文。但程序员可以创建自己的、适用于非标准要求的实现。
03. abstractownablesynchronizer/abstractqueuedsynchronizer/abstractqueuedlongsynchronizer
abstractqueuedsynchronizer就是被称之为aqs的类,它是一个非常有用的超类,可用来定义锁以及依赖于排队阻塞线程的其他同步器;reentrantlock,reentrantreadwritelock,countdownlatch,cyclicbarrier和semaphore等这些类都是基于aqs类实现的。abstractqueuedlongsynchronizer 类提供相同的功能但扩展了对同步状态的 64 位的支持。两者都扩展了类 abstractownablesynchronizer(一个帮助记录当前保持独占同步的线程的简单类)。
04. locksupport
locksupport提供“创建锁”和“其他同步类的基本线程阻塞原语”。
locksupport的功能和thread中的thread.suspend()和thread.resume()有点类似,locksupport中的park() 和 unpark() 的作用分别是阻塞线程和解除阻塞线程。但是park()和unpark()不会遇到“thread.suspend 和 thread.resume所可能引发的死锁”问题。
05. condition
condition需要和lock联合使用,它的作用是代替object监视器方法,可以通过await(),signal()来休眠/唤醒线程。
condition 接口描述了可能会与锁有关联的条件变量。这些变量在用法上与使用 object.wait 访问的隐式监视器类似,但提供了更强大的功能。需要特别指出的是,单个 lock 可能与多个 condition 对象关联。为了避免兼容性问题,condition 方法的名称与对应的 object 版本中的不同。
06. reentrantlock
reentrantlock是独占锁。所谓独占锁,是指只能被独自占领,即同一个时间点只能被一个线程锁获取到的锁。reentrantlock锁包括公平的reentrantlock和非公平的reentrantlock。公平的reentrantlock是指不同线程获取锁的机制是公平的,而非公平的reentrantlock则是指不同线程获取锁的机制是非公平的,reentrantlock是可重入的锁。
reentrantlock的uml类图如下:
(01) reentrantlock实现了lock接口。
(02) reentrantlock中有一个成员变量sync,sync是sync类型;sync是一个抽象类,而且它继承于aqs。
(03) reentrantlock中有公平锁类fairsync和非公平锁类nonfairsync,它们都是sync的子类。reentrantreadwritelock中sync对象,是fairsync与nonfairsync中的一种,这也意味着reentrantlock是公平锁或非公平锁中的一种,reentrantlock默认是非公平锁。
07. reentrantreadwritelock
reentrantreadwritelock是读写锁接口readwritelock的实现类,它包括子类readlock和writelock。reentrantlock是共享锁,而writelock是独占锁。
reentrantreadwritelock的uml类图如下:
(01) reentrantreadwritelock实现了readwritelock接口。
(02) reentrantreadwritelock中包含sync对象,读锁readerlock和写锁writerlock。读锁readlock和写锁writelock都实现了lock接口。
(03) 和reentrantlock一样,sync是sync类型;而且,sync也是一个继承于aqs的抽象类。sync也包括公平锁fairsync和非公平锁nonfairsync。
08. countdownlatch
countdownlatch是一个同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待。 
countdownlatch的uml类图如下:
countdownlatch包含了sync对象,sync是sync类型。countdownlatch的sync是实例类,它继承于aqs。
09. cyclicbarrier
cyclicbarrier是一个同步辅助类,允许一组线程互相等待,直到到达某个公共屏障点 (common barrier point)。因为该 barrier 在释放等待线程后可以重用,所以称它为循环 的 barrier。
cyclicbarrier的uml类图如下:
cyclicbarrier是包含了reentrantlock对象lock和condition对象trip,它是通过独占锁实现的。
cyclicbarrier和countdownlatch的区别是:
(01) countdownlatch的作用是允许1或n个线程等待其他线程完成执行;而cyclicbarrier则是允许n个线程相互等待。
(02) countdownlatch的计数器无法被重置;cyclicbarrier的计数器可以被重置后使用,因此它被称为是循环的barrier。
10. semaphore
semaphore是一个计数信号量,它的本质是一个共享锁。
信号量维护了一个信号量许可集。线程可以通过调用acquire()来获取信号量的许可;当信号量中有可用的许可时,线程能获取该许可;否则线程必须等待,直到有可用的许可为止。 线程可以通过release()来释放它所持有的信号量许可。
semaphore的uml类图如下:
和reentrantlock一样,semaphore包含了sync对象,sync是sync类型;而且,sync也是一个继承于aqs的抽象类。sync也包括公平信号量fairsync和非公平信号量nonfairsync。
以上就是java中的锁--同步锁和juc包中的锁的详细内容。
其它类似信息

推荐信息