ReentrantLock:重入鎖胚吁,它是唯一一個實(shí)現(xiàn)了 Lock 接口的類攀细。
synchronized 和 ReentrantLock 都是可重入鎖
獨(dú)占鎖:ReentrantLock艰匙、ReentrantReadWriteLock.WriteLock
共享鎖:ReentrantReadWriteLock.ReadLock现喳、CountDownLatch鞋拟、CyclicBarrier盘寡、Semaphore
其實(shí)現(xiàn)方式為:
獨(dú)占鎖實(shí)現(xiàn)的是tryAcquire(int)尽狠、tryRelease(int)
共享鎖實(shí)現(xiàn)的是tryAcquireShared(int)衔憨、tryReleaseShared(int)
實(shí)現(xiàn)原理:
是通過為每個鎖關(guān)聯(lián)一個請求計(jì)數(shù)和一個占有它的線程。
當(dāng)計(jì)數(shù)為0時袄膏,認(rèn)為鎖是未被占有的践图。
線程請求一個未被占有的鎖時,jvm講記錄鎖的占有者沉馆,并且講請求計(jì)數(shù)器置為1 码党。
如果同一個線程再次請求這個鎖,計(jì)數(shù)將遞增斥黑;
每次占用線程退出同步塊揖盘,計(jì)數(shù)器值將遞減。
直到計(jì)數(shù)器為0,鎖被釋放锌奴。
重入鎖指的是線程在獲得鎖之后兽狭,再次獲取該鎖不需要阻塞,而是直接關(guān)聯(lián)一次計(jì)數(shù)器增加重入次數(shù)鹿蜀。
比如調(diào)用 demo1 方法獲得了當(dāng)前的對象鎖箕慧,然后在這個方法中再去調(diào)用demo2,
demo2 中的存在同一個實(shí)例鎖茴恰,這個時候當(dāng)前線程會因?yàn)闊o法獲得
demo2 的對象鎖而阻塞颠焦, 如果 不是 重入鎖 就會產(chǎn)生死鎖。
重入鎖的設(shè)計(jì)目的
重入鎖的設(shè)計(jì)目的是避免線程的死鎖往枣。
public class ReentrantDemo{
public synchronized void demo1(){
System.out.println("begin:demo1");
demo2();
}
public void demo2(){
System.out.println("begin:demo1");
synchronized (this){
}
}
public static void main(String[] args) {
ReentrantDemo rd=new ReentrantDemo();
new Thread(rd.demo1()).start();
}
}
public class AtomicDemo {
private static int count=0;
static Lock lock=new ReentrantLock();
public static void inc(){
//重入鎖
lock.lock();
try {
Thread.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
count++;
lock.unlock();
}
public static void main(String[] args) throws InterruptedException {
for(int i=0;i<200;i++){
new Thread(()->{AtomicDemo.inc();}).start();
}
Thread.sleep(4000);System.out.println("result:"+count);
}
}