java基础---多线程---JUC锁

Lock接口
lock是一个接口面向的是锁的使用者,比起重量级锁synchronized他提供了粒度更细的锁控制。包括锁的获取,尝试获取,释放,响应中断以及超时等等。
Lock接口提供了获取和释放锁的方法。
 
能够按照不同的方式获取锁:
中断获取:当线程获取锁了,这个时候被中断,就会抛出异常同时释放锁。
超时获取:给定时间去获取锁,这个时间内能够被中断,同时到时间没获取到就返回。
 

AQS(AbstractQueuedSynchronized)
AQS抽象队列同步器是锁真正实现的载体,面向的是锁的开发者。
内部维护了两种队列,同步队列和condition等待队列。
当多个线程并发的想要获取锁的时候,只有一个线程获取到,其他线程会被包装成一个一个的node节点通过CAS的方式插入到同步队列末尾,这个同步队列是具有头尾节点的双向链表,头尾节点都是空的。同时每个节点会自旋判断是否再次获取锁。
如果是公平锁的实现形式,那么只有头结点的下个节点也就是第一个节点有机会获取到锁。如果是非公平锁的实现形式,那么每个节点都有机会获取到锁。
 
等待队列也是通过lock锁的newCondition方法创建出来的,可以创建多个。呢也是一个带头尾节点双向链表,如果一个线程获取锁,调用await()方法后就会被包裹成一个节点Node插入到等待队列中。当其他线程获取到lock锁后调用singnal方法才能够唤醒。
 
 

ReentrantLock重入锁
ReentrantLock重入锁,他是一种独占锁。
1.允许单个线程可以重复获取锁,内部使用一个int类型的state属性记录重入次数。同一个线程每多锁一次,state++;解锁一次state--
2.分公平锁和非公平锁两种实现类型,内部写了两个类,分别继承自AQS,根据公平和非公平实现了两种锁。两种锁的区别在于节点自旋的判断不同。公平锁,每个节点会判断自己是不是第一个节点也就是头结点的下一个节点,同时尝试获取锁;非公平每个节点都尝试获取锁,这样效率会更高,但是相应的也会出现饥饿的问题。
主要是tryAcquire方法的不同。
1.公平锁每个在同步队列的节点自旋判断的时候会做两件事:1.尝试获取锁,2.判断是否为头结点
2.非公平锁每个同步队列中的节点自旋判断的时候只做一件事:1.尝试获取锁
3.Reentrantlock是独占锁的实现方式,实现了公平锁和非公平锁。
实现方式是通过AQS的方法实现的。
 
 

ReentranReadWriteLock读写锁
内部实现两种锁,读锁是共享锁,写锁是独占锁。都继承自AQS进行了具体实现。
同时维护了一个state状态,高16位是读锁状态,第十六位是写锁状态。
多个线程可以同时获取读锁进行读操作,但是当一个线程获取写锁之后,其他线程就无法获取写锁和读锁了。写锁的获取必须等待所有读锁释放。
 

CountDownLatch
维护线程的执行顺序,让一些线程等待另外一些线程执行。内部是AQS共享锁的实现方式,初始化一个countdownlatch对象的时候有一个state状态位。
多个线程在内部调用某个countDownLatch对象的await()方法进入阻塞等待唤醒。
其他线程调用countdown()方法将state减减,直到0的时候刚刚那些阻塞的线程就能够唤醒了。
这样能够按先后顺序来执行线程。

CyclicBarrier
一种屏障锁。让几个线程一起到达一个屏障后再一起执行。
使用方式:
1.新建一个cyclicbarrier,同时初始化计数器
2.线程的run方法中执行cyclicbarrier.await()方法将当前线程挂起
3.当到达计数器的线程挂起之后再一起执行线程之后的内容
补充使用方式:可以在挂起的时候让线程去执行另一个方法。这里初始化cyclicbarrier的时候就要进行处理。

猜你喜欢

转载自www.cnblogs.com/buptyuhanwen/p/9546807.html
今日推荐