- WHO ?
我是一個普通當(dāng)程序員,目前正在學(xué)習(xí)java并發(fā)編程,為學(xué)習(xí)netty做準(zhǔn)備。 - WHAT & WHEN ?
主題呢,和標(biāo)題一樣理解一下Java中當(dāng)Lock & Condition - Why ?
寫這篇文章,主要是講解一下Lock和Condition。同時呢,給一些和我一樣在學(xué)習(xí)java并發(fā)編程當(dāng)同學(xué)提供一些參考。我在學(xué)習(xí)Lock和Condition的時候,覺得很迷茫。看別人的博客什么的都能看的懂,但是自己寫的時候就各種錯誤。 - How ?
直接步入正題:
Lock顧名思義就是鎖的意思。
Condition翻譯過來就是"條件"的意思。那么Condition是誰的條件呢?看一下Condition是怎么創(chuàng)建的就知道了。
Lock lock = new ReentrantLock();
Conditon notFull = lock.newCondition();
從上面的代碼,我們可以一眼就看出所謂的"條件",就是Lock的條件。你可以理解為Lock的成員變量(你可以姑且這么認(rèn)為)。有了以上基礎(chǔ)以后,我們再來看一下下面這段代碼:
import java.util.Queue;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class MyBlockedQueue<T> {
final Lock lock = new ReentrantLock();
final Condition notFull = lock.newCondition();
final Condition notEmpty = lock.newCondition();
private Queue queue = new ArrayBlockingQueue(5);
void enq(T e){
lock.lock();
try {
while (queue.size() == 5){
notFull.await();
}
// TODO: 2019/8/26 do something for enque
notEmpty.signal();
}catch (InterruptedException ex) {
ex.printStackTrace();
} finally {
lock.unlock();
}
}
void denq(){
lock.lock();
try {
while (!queue.isEmpty()){
notEmpty.await();
}
// TODO: 2019/8/26 do something for denque
notFull.signal();
}catch (InterruptedException ex){
ex.printStackTrace();
} finally {
lock.unlock();
}
}
}
代碼理解:
上面的代碼定義了enq和denq倆個方法,這倆個方法是互斥的,所以聲明了一個變量lock。lock是一個可重入鎖(關(guān)于可重入鎖,后續(xù)會講到詳細(xì)當(dāng)內(nèi)容)。lock鎖有倆個條件(成員變量)notFull和notEmpty。
線程A執(zhí)行enq方法時,先獲取鎖,然后判斷隊列是否是滿的,如果是滿的,則等待deq方法被執(zhí)行;隨后,當(dāng)線程A執(zhí)行denq()方法時,獲取鎖,然后發(fā)現(xiàn)隊列并不是空的,可以執(zhí)行deq業(yè)務(wù)邏輯,然后喚起其他等待notFull的線程。這個時候線程A的enq方法發(fā)現(xiàn),queue.size()==5的條件不滿足了,執(zhí)行enq業(yè)務(wù)邏輯。
當(dāng)其他線程想要同時執(zhí)行該對象當(dāng)enq方法時,因?yàn)楂@取不到鎖,所以會產(chǎn)生線程阻塞。
- Q&A
Q1:為什么使用await()和signal(),不使用wait()和notify()?
A1:這里涉及到j(luò)ava sdk倆套并發(fā)設(shè)計。使用Lock和Condition的話只能配套使用await()和signal();wait()和notify()是配合synchronized使用。如果混用,那么你的程序會出各種問題。
有其他問題,可以關(guān)注公眾號‘麻油地’,留言,我會及時進(jìn)行回復(fù),解答。