wordpress上傳swf網(wǎng)站優(yōu)化排名公司哪家好
ReentrantLock
相對于synchronized它具備如下特點
· 可中斷
· 可以設置超時時間
· 可以設置為公平鎖
· 支持多個條件變量(多個wait set,不同于synchronized的wait set,ReentrantLock的wait set在同一條件下notify才能喚醒WATING狀態(tài)的線程)
與synchronized一樣,都支持可重入
基本語法
//獲取鎖
ReentrantLock reentrantLock = new ReentrantLock();
reentrantLock.lock();
try{//臨界區(qū)
}finally{//釋放鎖reentrantLock.unlock();
}
可重入
可重入是指同一個線程如果首次獲得了這把鎖,那么因為它是這把鎖的持有者,因此有權(quán)力再次獲取這把鎖。如果是不可重入鎖,那么第二次獲得鎖時,自己也會被鎖擋住
代碼體現(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()來生成的鎖才能打斷
代碼體現(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 {//如果沒有競爭那么此方法就會獲取lock對象鎖//如果有競爭就進入阻塞隊列,可以被其他線程用 interruput 方法打斷log.debug("嘗試獲得鎖");lock.lockInterruptibly();} catch (InterruptedException e) {e.printStackTrace();log.debug("沒有獲得到鎖");return;}try {log.debug("獲取到鎖");}finally {lock.unlock();}}, "t1");lock.lock();t1.start();Thread.sleep(1000);log.debug("打斷 t1");t1.interrupt();}
}
鎖超時
立刻失敗
@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();}}
含超時時間的
@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解決哲學家用餐問題
筷子類
class Chopstick extends ReentrantLock {String name;public Chopstick(String name) {this.name = name;}@Overridepublic String toString() {return "Chopstick{" +"name='" + name + '\'' +'}';}
}
哲學家類
@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("哲學1",c1,c2).start();new Philosopher("哲學2",c2,c3).start();new Philosopher("哲學3",c3,c4).start();new Philosopher("哲學4",c4,c5).start();new Philosopher("哲學5",c5,c1).start();}
}
公平鎖
ReentrantLock默認是不公平的,但是可以通過構(gòu)造方法改成公平的
ReentrantLock reentrantLock = new ReentrantLock(true);
公平鎖一般沒有必要,會降低并發(fā)度。
條件變量
synchronized中也有條件變量,就是waitSet休息室,當條件不滿足時進入waitSet等待
ReentrantLock的條件變量比synchronized強大之處在于,它是支持多個條件變量的,這就好比
· synchronized是那些不滿足條件的線程都在一間休息室等消息
· 而ReentrantLock支持多間休息室,喚醒時也是按休息室來喚醒
使用流程
· await前需要獲取鎖
· await執(zhí)行后,會釋放鎖,進入conditionObject等待
· await的線程被喚醒(或打斷、或超時)取重新競爭lock鎖
· 競爭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("有煙沒");while (!hasSmoke) {log.debug("沒煙我先休息");try {smoke.await();} catch (InterruptedException e) {e.printStackTrace();}}log.debug("有煙,那沒事了");}finally {lock.unlock();}},"小男").start();new Thread(()->{lock.lock();try {log.debug("有飯沒");while (!hasEat){log.debug("沒飯我先休息了");try {eat.await();} catch (InterruptedException e) {e.printStackTrace();}}log.debug("有飯那沒事了");}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();}
}