獨占鎖:在任一時刻只能有一個線程獲取到鎖埠帕,可以執(zhí)行瞳购。其他線程被阻塞话侄,進去等待隊列
共享鎖:共享鎖允許多個線程同時運行,通常情況下学赛,共享鎖內(nèi)部維護了若干個執(zhí)行許可年堆,每個線程執(zhí)行的時候獲取一個許可,運行結(jié)束的時候釋放許可盏浇。當一個線程請求執(zhí)行時变丧,如果共享鎖已經(jīng)沒有許可,那么該線程進入等待隊列绢掰。
注:可以認為獨占式同步組件是共享式同步組件的一個特例痒蓬,其只有1個許可
lock接口獨占鎖示例
import java.util.Date;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class LockDemo {
public static void main(String[] args) {
final Lock lock = new ReentrantLock();
new Thread("Thread A"){
@Override
public void run(){
lock.lock();//加鎖
try{
work();
}finally {
lock.unlock();//釋放鎖
}
}
}.start();
new Thread("Thread B"){
@Override
public void run(){
lock.lock();//加鎖
try{
work();
}finally {
lock.unlock();//釋放鎖
}
}
}.start();
new Thread("Thread C"){
@Override
public void run(){
lock.lock();//加鎖
try{
work();
}finally {
lock.unlock();//釋放鎖
}
}
}.start();
System.out.println("start--------------");
}
@SuppressWarnings("static-access")
public static void work(){
try {
System.out.println(Thread.currentThread().getName()+" started to work,currrentTime:"+new Date().toLocaleString());
Thread.currentThread().sleep(1000);
System.out.println(Thread.currentThread().getName()+" wnd work,currrentTime:"+new Date().toLocaleString());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
運行結(jié)果
start--------------
Thread B started to work,currrentTime:2017-1-20 16:51:09
Thread B wnd work,currrentTime:2017-1-20 16:51:10
Thread A started to work,currrentTime:2017-1-20 16:51:10
Thread A wnd work,currrentTime:2017-1-20 16:51:11
Thread C started to work,currrentTime:2017-1-20 16:51:11
Thread C wnd work,currrentTime:2017-1-20 16:51:12
分析
從結(jié)果看出,B先獲取到鎖曼月,等到執(zhí)行完畢谊却,A才獲取到鎖柔昼,才開始執(zhí)行
ReentranLock共享鎖示例
public class ReentrantLockDemo {
public static void main(String[] args) {
ReentrantLock lock = new ReentrantLock();
System.out.println(lock.getHoldCount());//沒有調(diào)用lock之前哑芹,hold count為0
lock.lock();
System.out.println(lock.getHoldCount());
lock.lock();
System.out.println(lock.getHoldCount());
lock.unlock();
System.out.println(lock.getHoldCount());
lock.unlock();
System.out.println(lock.getHoldCount());
}
}
運行結(jié)果
0
1
2
1
0
分析
一個線程(本案例就是主線程)的確可以多次持有同一個鎖。每當調(diào)用lock方法時捕透,次數(shù)+1聪姿,每當調(diào)用unlock方法時,次數(shù)-1乙嘀。我們看到出現(xiàn)了2末购,
這事實上就體現(xiàn)了所謂的可重入。
需要注意的是:當getHoldCount()不為0的時候虎谢,表示鎖當前正在被某個線程使用盟榴,只有當其為0的時候,其他線程才有機會獲取這個鎖