Java培训教程之使用Lock取代synchronized
在多線程中,1.5版本之前,我們都使用同步代碼塊或者同步方法來解決線程安全問題
比如:
同步代碼塊
synchronized(鎖對象){
功能代碼;
}
同步方法
public synchronized void test(){
功能代碼;
}
在1.5版本,在java的工具類包中,java.util.concurrent.locks 中,推出了最新的
解決線程安全的方法,就是Lock+Condition的方式,
那這兩種方式之間的關系和區別是什么呢?
加入對于線程常見的生產者消費者模式,我們使用兩種方式實現,來看看他們的區別:
第一種,使用synchronized
我們完成一個男人掙錢女人花的例子
需求是如果沒錢,男人線程掙一次錢,等待,然后喚醒女人去花錢,花完錢,等待,喚醒
男人去掙錢,一直循環這個過程,將男人線程看做生產線程,女人線程看做消費線程。
代碼如下:
//首先完成共享數據
class Person{
String name;
boolean isMoney=true;
//掙錢
public void zhengQian(){
synchronized(this){
while(!isMoney){
try{wait();}catch(Exception e){}
}
name=“男人”;
System.out.println(Thread.currentThread().getName()+name+"—掙錢—");
isMoney=!isMoney;
notifyAll();//叫醒所有
}
}
//花錢
public void huaQian(){
synchronized(this){
while(isMoney){
try{wait();}catch(Exception e){}
}
name=“women。。。。人”;
System.out.println(Thread.currentThread().getName()+name+"—花=========錢—");
isMoney=!isMoney;
notifyAll();//叫醒所有
}
}
}
//輸入線程
class In implements Runnable{
Person p=null;
In(Person p){
this.p=p;
}
public void run(){
while(true){
p.zhengQian();
}
}
}
//輸出線程
class Out implements Runnable{
Person p=null;
Out(Person p){
this.p=p;
}
public void run(){
while(true){
p.huaQian();
}
}
}
從代碼中可以看出,對于同步代碼塊或者同步方法來說,都是以鎖對象this來控制其鎖定的代碼的。
api中也告訴我們:
Lock 實現提供了比使用 synchronized 方法和語句可獲得的更廣泛的鎖定操作。此實現允許更靈活的結構,可以具有差別很大的屬性,可以支持多個相關的 Condition 對象。
那使用Lock+Condition怎么來實現呢?
代碼如下:
import java.util.concurrent.locks.*;
class Person{
String name;
boolean isMoney=true;
Lock lock=new ReentrantLock();
Condition in=lock.newCondition();
Condition out=lock.newCondition();
//掙錢
public void zhengQian(){
lock.lock();
try{
while(!isMoney){
try{in.wait();}catch(Exception e){}
}
name=“男人”;
System.out.println(Thread.currentThread().getName()+name+"—掙錢—");
isMoney=!isMoney;
out.signal();//叫醒對方
}finally{
lock.unlock();
}
}
//花錢
public void huaQian(){
lock.lock();
try{
while(!isMoney){
try{out.wait();}catch(Exception e){}
}
name=“women。。。。人”;
System.out.println(Thread.currentThread().getName()+name+"—花=========錢—");
isMoney=!isMoney;
in.signal();//叫醒對方
}finally{
lock.unlock();
}
}
}
對比發現,Lock+Condition的方式是使用Condition對象來具體操作現場的等待和喚醒的,
也就是對于生產線程有專屬的生成線程的Condition對象,對消費線程有專屬的消費線程的Condition
對象,當等待或者喚醒時可以精確的控制是哪方線程,同步代碼塊或者同步方法在喚醒時,不能精確的
喚醒對方,所以只能喚醒全部,這時候增加了線程的判斷次數,明顯,Lock+Condition是優于synchronized的方式的
接下來我們分析下Lock和Condition的關系
Lock的子類對象是來取代synchronized的,也就是鎖,Condition只是鎖的操作對象
取代的是以前的鎖對象,都擁有等待和喚醒的方法,雖然名字不同,Condition主要是對鎖的操作對象
進行分類,如下圖:
上圖中,一個Lock對象,創建出來三個Condition對象 x,y,z
也就是以后執行這個鎖的線程將會被分成三類線程,比如如果執行x.await(),執行這段代碼的
三個綠色線程將會進入等待狀態,再比如z中三個紅色線程都處于等待狀態,如果執行z.signal(),將會喚醒執行z的三個紅色線程中的某一個,這樣代碼就可以正常運行了。
藍色線兩側分別表示兩個Lock的子類對象,每一個lock的Condition之間可以互相操作,對于兩個
鎖之間的Condition,比如,x和Q,就沒有直接的關系了
好了,這篇文章主要說明下Lock+Condition方式來取代synchronized,希望對大家有所幫助。
本文來自千鋒教育,轉載請注明出處。
總結
以上是生活随笔為你收集整理的Java培训教程之使用Lock取代synchronized的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: windows系统下实现Redis的配置
- 下一篇: 教大家python读取一行一行文件内容的