wordpress上傳swf網(wǎng)站優(yōu)化排名公司哪家好
ReentrantLock
相對(duì)于synchronized它具備如下特點(diǎn)
· 可中斷
· 可以設(shè)置超時(shí)時(shí)間
· 可以設(shè)置為公平鎖
· 支持多個(gè)條件變量(多個(gè)wait set,不同于synchronized的wait set,ReentrantLock的wait set在同一條件下notify才能喚醒WATING狀態(tài)的線程)
與synchronized一樣,都支持可重入
基本語(yǔ)法
//獲取鎖
ReentrantLock reentrantLock = new ReentrantLock();
reentrantLock.lock();
try{//臨界區(qū)
}finally{//釋放鎖reentrantLock.unlock();
}
可重入
可重入是指同一個(gè)線程如果首次獲得了這把鎖,那么因?yàn)樗沁@把鎖的持有者,因此有權(quán)力再次獲取這把鎖。如果是不可重入鎖,那么第二次獲得鎖時(shí),自己也會(huì)被鎖擋住
代碼體現(xiàn)
@Slf4j(topic = "c.Demo")
public class Demo {private static ReentrantLock reentrantLock = new ReentrantLock();public static void main(String[] args) {reentrantLock.lock();try {log.debug("enter main");m1();}finally {reentrantLock.unlock();}}public static void m1(){reentrantLock.lock();try {log.debug("enter m1");m2();}finally {reentrantLock.unlock();}}public static void m2(){reentrantLock.lock();try {log.debug("enter m2");}finally {reentrantLock.unlock();}}
}
可打斷
用lockInterruptibly()來(lái)生成的鎖才能打斷
代碼體現(xiàn)
@Slf4j(topic = "c.Demo2")
public class Demo2 {private static ReentrantLock lock = new ReentrantLock();public static void main(String[] args) throws InterruptedException {Thread t1 = new Thread(() -> {try {//如果沒(méi)有競(jìng)爭(zhēng)那么此方法就會(huì)獲取lock對(duì)象鎖//如果有競(jìng)爭(zhēng)就進(jìn)入阻塞隊(duì)列,可以被其他線程用 interruput 方法打斷log.debug("嘗試獲得鎖");lock.lockInterruptibly();} catch (InterruptedException e) {e.printStackTrace();log.debug("沒(méi)有獲得到鎖");return;}try {log.debug("獲取到鎖");}finally {lock.unlock();}}, "t1");lock.lock();t1.start();Thread.sleep(1000);log.debug("打斷 t1");t1.interrupt();}
}
鎖超時(shí)
立刻失敗
@Slf4j(topic = "c.Demo3")
public class Demo3 {private static ReentrantLock lock = new ReentrantLock();public static void main(String[] args) {Thread t1 = new Thread(()->{log.debug("嘗試獲得鎖");if (!lock.tryLock()) {log.debug("獲取不到鎖");return;}try {log.debug("獲取到鎖");}finally {lock.unlock();}},"t1");lock.lock();log.debug("獲取到鎖");t1.start();}}
含超時(shí)時(shí)間的
@Slf4j(topic = "c.Demo3")
public class Demo3 {private static ReentrantLock lock = new ReentrantLock();public static void main(String[] args) throws InterruptedException {Thread t1 = new Thread(()->{log.debug("嘗試獲得鎖");try {if (!lock.tryLock(2, TimeUnit.SECONDS)) {log.debug("獲取不到鎖");return;}} catch (InterruptedException e) {e.printStackTrace();log.debug("獲取不到鎖");return;}try {log.debug("獲取到鎖");}finally {lock.unlock();}},"t1");lock.lock();log.debug("獲取到鎖");t1.start();Thread.sleep(1000);log.debug("釋放了鎖");lock.unlock();}}
用ReentrantLock解決哲學(xué)家用餐問(wèn)題
筷子類
class Chopstick extends ReentrantLock {String name;public Chopstick(String name) {this.name = name;}@Overridepublic String toString() {return "Chopstick{" +"name='" + name + '\'' +'}';}
}
哲學(xué)家類
@Slf4j(topic = "c.Philosopher")
class Philosopher extends Thread{Chopstick left;Chopstick right;public Philosopher(String name, Chopstick left, Chopstick right){super(name);this.left = left;this.right = right;}@Overridepublic void run() {while (true){//嘗試獲得左手筷子if (left.tryLock()) {try {//嘗試獲取右手筷子if (right.tryLock()) {try {eat();}finally {right.unlock();}}}finally {left.unlock();//釋放手里的左筷子}}}}private void eat(){log.debug("eating...");try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}
}
test類
@Slf4j(topic = "c.SoleDeadLockDemo")
public class SoleDeadLockDemo {public static void main(String[] args) {Chopstick c1 = new Chopstick("1");Chopstick c2 = new Chopstick("2");Chopstick c3 = new Chopstick("3");Chopstick c4 = new Chopstick("4");Chopstick c5 = new Chopstick("5");new Philosopher("哲學(xué)1",c1,c2).start();new Philosopher("哲學(xué)2",c2,c3).start();new Philosopher("哲學(xué)3",c3,c4).start();new Philosopher("哲學(xué)4",c4,c5).start();new Philosopher("哲學(xué)5",c5,c1).start();}
}
公平鎖
ReentrantLock默認(rèn)是不公平的,但是可以通過(guò)構(gòu)造方法改成公平的
ReentrantLock reentrantLock = new ReentrantLock(true);
公平鎖一般沒(méi)有必要,會(huì)降低并發(fā)度。
條件變量
synchronized中也有條件變量,就是waitSet休息室,當(dāng)條件不滿足時(shí)進(jìn)入waitSet等待
ReentrantLock的條件變量比synchronized強(qiáng)大之處在于,它是支持多個(gè)條件變量的,這就好比
· synchronized是那些不滿足條件的線程都在一間休息室等消息
· 而ReentrantLock支持多間休息室,喚醒時(shí)也是按休息室來(lái)喚醒
使用流程
· await前需要獲取鎖
· await執(zhí)行后,會(huì)釋放鎖,進(jìn)入conditionObject等待
· await的線程被喚醒(或打斷、或超時(shí))取重新競(jìng)爭(zhēng)lock鎖
· 競(jìng)爭(zhēng)lock鎖成功后,從await后繼續(xù)執(zhí)行
@Slf4j(topic = "c.Demo5")
public class Demo5 {static final ReentrantLock lock = new ReentrantLock();static private boolean hasSmoke = false;static private boolean hasEat = false;static Condition smoke = lock.newCondition();static Condition eat = lock.newCondition();public static void main(String[] args) throws InterruptedException {new Thread(()->{lock.lock();try {log.debug("有煙沒(méi)");while (!hasSmoke) {log.debug("沒(méi)煙我先休息");try {smoke.await();} catch (InterruptedException e) {e.printStackTrace();}}log.debug("有煙,那沒(méi)事了");}finally {lock.unlock();}},"小男").start();new Thread(()->{lock.lock();try {log.debug("有飯沒(méi)");while (!hasEat){log.debug("沒(méi)飯我先休息了");try {eat.await();} catch (InterruptedException e) {e.printStackTrace();}}log.debug("有飯那沒(méi)事了");}finally {lock.unlock();}},"小女").start();Thread.sleep(1000);new Thread(()->{lock.lock();try {log.debug("送飯的到了");hasEat = true;eat.signal();}finally {lock.unlock();}},"送飯的").start();Thread.sleep(1000);new Thread(()->{lock.lock();try {log.debug("送煙的到了");hasSmoke = true;smoke.signal();}finally {lock.unlock();}},"送煙的").start();}
}