并發(fā)控制方法

解決問題:為多線程婴谱、多任務(wù)間的協(xié)作和數(shù)據(jù)共享提供并發(fā)控制。常用方法:內(nèi)部鎖、重入鎖勘究、讀寫鎖、信號量等斟冕。
一口糕、volatile
由于每個線程有自己的私有內(nèi)存空間(計數(shù)器、本地方法棧磕蛇、虛擬機棧)景描,同時還保存了主內(nèi)存中的共享變量的值的拷貝。因此如果線程想改變自己工作內(nèi)存的數(shù)據(jù)時秀撇,對其他線程是不可見的超棺。為此可以使用volatile關(guān)鍵字迫使所有線程讀寫主內(nèi)存中的對應(yīng)變量,從而使得其在多線程間可見呵燕。
聲明為volatile的變量解決了線程間數(shù)據(jù)共享問題棠绘,可以保證:
1.其他線程修改了變量,可以立即反饋到當(dāng)前線程
2.確保當(dāng)前線程修改了變量再扭,即使會寫到主內(nèi)存氧苍,對其他線程可見
3.編譯期可以保證其變量有序
主內(nèi)存和工作內(nèi)存?泛范?
volatile特別適合于在不同線程中進行控制狀態(tài)標(biāo)記量

volatile boolean inited = false; // 線程1
context = loadContext();
        
inited = true; // 線程2
while(!inited) {
  sleep();
}
doSomethingWithConfig(context);

分析:
上面的代碼利用volatile修飾的inited保證上下文的初始化是否完成让虐,線程1初始化,線程2必須保證線程1初始化完成才能繼續(xù)進行下去罢荡。加入volatile可以保證變量inited的改變及時刷到主存中赡突,可以被其他線程及時看到。
二区赵、synchronized
采用同步方式
1.使用:
一種是鎖定一個對象的方法惭缰,如 public synchronized void method(),當(dāng)method方法調(diào)用時,調(diào)用線程首先獲得當(dāng)前對象的鎖笼才,若當(dāng)前對象鎖被其他線程持有从媚,則調(diào)用線程會等待,方法結(jié)束后患整,釋放對象鎖拜效,以上方法等價于
public void method(){ synchronized(this){ } }
一種是鎖定代碼塊,可以精確的控制并發(fā)代碼各谚,

public void method(Object so ){
some code here ;
synchronized(so){
  ...
}
other code here ;
}

一種是加在static方法上紧憾,鎖的是當(dāng)前Class對象,因此所有對該方法的調(diào)用昌渤,都要獲取該Class對象的鎖赴穗。
以上實際上鎖的是對象(所有同步代碼段用的同一個對象獨占鎖),只能防止多個線程同時執(zhí)行同一個對象的同步代代碼碼段,即使不同的同步代碼段也是不能同時訪問的般眉。
2.notify和wait
通常情況下了赵,雖然實現(xiàn)了同步效果,但是對于復(fù)雜的業(yè)務(wù)邏輯甸赃,常常配合Object對象的wait和notify方法柿汛。
wait過程中,釋放對象鎖埠对,典型用法:

synchronized (obj )
{
    while (condition)
            obj.wait();
    //收到通知后络断,繼續(xù)執(zhí)行
}

首先在wait前獲得對象獨占鎖,循環(huán)進行狀態(tài)判斷项玛,跳出后貌笨,wait方法執(zhí)行后當(dāng)前線程會釋放對象鎖,供其他線程使用
當(dāng)?shù)却趏bj對象上的線程被notify后襟沮,會獲得當(dāng)前當(dāng)前對象的獨占鎖锥惋,并繼續(xù)運行。如果多個線程在等待开伏,那么notify則隨機選擇一個
如下示例實現(xiàn)一個阻塞隊列:

public class BlockQueue  {
    private List arrayList=new ArrayList();
    public  synchronized Object pop() throws InterruptedException {
        while(arrayList.size()==0)
            this.wait();
        if(arrayList.size()>0)
        {
            return  arrayList.remove(0);
        }
        else  return  null;

    }
    public  synchronized void add(Object obj)
    {
        arrayList.add(obj);
        this.notify();
    }
}

同時Object還有wait(long timeout)和notifyAll()將喚醒所有等待在當(dāng)前對象上的所有線程

三净刮、ReentrantLock重入鎖
1.特性
(1).高并發(fā)下性能好,可中斷硅则、可定時
(2).公平鎖和非公平鎖:公平鎖能保證線程間公平競爭鎖對象淹父,對鎖的獲取是有序的,非公平則無序怎虫,可能會出現(xiàn)插隊現(xiàn)象
(3).必須手動調(diào)用unlock,否則會一直鎖定程序暑认,而synchronized隨著jvm自動釋放
2.重要方法
(1)lock:獲得鎖,如果鎖被占用大审,就一直等待
(2)lockInerruptibly : 獲得鎖蘸际,但優(yōu)先響應(yīng)中斷
(3)tryLock:嘗試獲得鎖,成功返回true徒扶;失敗返回false粮彤。該方法不等待,立即返回姜骡。
(4)tryLock(long timeout,TimeUnit unit)导坟,在給定時間內(nèi)獲得鎖
(5)unlock:釋放鎖
注:lock方法會一直等待,直到獲得鎖圈澈,同時在等待鎖的過程中惫周,線程不會響應(yīng)中斷;而lockInterruptibly在線程等待鎖過程中康栈,可以優(yōu)先響應(yīng)中斷递递。
總結(jié):ReentrantLock重入鎖提供了豐富的鎖控制喷橙,如無等待的tryLock,還有優(yōu)先響應(yīng)中斷的lockInterruptibly的鎖登舞。在鎖競爭激烈的情況贰逾,這些靈活的鎖可以提供更優(yōu)的方案,從而提升系統(tǒng)性能

四菠秒、ReadWriteLock讀寫鎖
jdk5提供的讀寫分離鎖疙剑,可以有效減少鎖競爭,提升系統(tǒng)性能稽煤。在讀多的情況下,可以做到多個線程并行讀操作囚戚,在寫的時候還是使用鎖酵熙。
適合于讀多寫少的場景

五、condition對象
具體參考:http://www.reibang.com/p/be2dc7c878dc

六驰坊、Semaphone信號量
信號量為多線程協(xié)作提供了更強大的控制方法匾二,是對鎖的擴展。無論是的內(nèi)部鎖synchronized還是重入鎖ReentrantLock都限制了只有一個線程訪問一個資源拳芙,而信號量支持多個線程同時訪問一個資源察藐。
方法:
1.構(gòu)造函數(shù) :需要指定信號量的準(zhǔn)入數(shù),即多少個線程同時訪問某個資源舟扎。

image.png

信號量對鎖進行了擴展分飞,可以限定對某個資源的最大可訪問線程數(shù)。

七睹限、ThreadLocal 線程局部變量
能保證不同線程中的局部變量獨立性譬猫,但是不屬于多線程的數(shù)據(jù)共享。
機制:不提供鎖羡疗,而是使用以空間換時間的方式染服,為每個線程提供變量的獨立副本,以保證線程安全叨恨,因此它不屬于多線程間數(shù)據(jù)共享的方案

public class MyThread implements  Runnable {
   public static  final ThreadLocal<Date> localvar=new ThreadLocal<>();
   private long time;
   public  MyThread(long time )
   {
       this.time=time;
   }
   @Override
    public  void run()
   {
        Date d=new Date(time);
        for (int i=0;i<50000;i++)
        {
            localvar.set(d);
            if(localvar.get().getTime()!=time)
                System.out.println("id="+time+"locallvar="+localvar.get().getTime());
        }
   }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末柳刮,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子痒钝,更是在濱河造成了極大的恐慌秉颗,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,546評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件送矩,死亡現(xiàn)場離奇詭異站宗,居然都是意外死亡,警方通過查閱死者的電腦和手機益愈,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,224評論 3 395
  • 文/潘曉璐 我一進店門梢灭,熙熙樓的掌柜王于貴愁眉苦臉地迎上來夷家,“玉大人,你說我怎么就攤上這事敏释】饪欤” “怎么了?”我有些...
    開封第一講書人閱讀 164,911評論 0 354
  • 文/不壞的土叔 我叫張陵钥顽,是天一觀的道長义屏。 經(jīng)常有香客問我,道長蜂大,這世上最難降的妖魔是什么闽铐? 我笑而不...
    開封第一講書人閱讀 58,737評論 1 294
  • 正文 為了忘掉前任,我火速辦了婚禮奶浦,結(jié)果婚禮上兄墅,老公的妹妹穿的比我還像新娘。我一直安慰自己澳叉,他們只是感情好隙咸,可當(dāng)我...
    茶點故事閱讀 67,753評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著成洗,像睡著了一般五督。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上瓶殃,一...
    開封第一講書人閱讀 51,598評論 1 305
  • 那天充包,我揣著相機與錄音,去河邊找鬼遥椿。 笑死误证,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的修壕。 我是一名探鬼主播愈捅,決...
    沈念sama閱讀 40,338評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼慈鸠!你這毒婦竟也來了蓝谨?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,249評論 0 276
  • 序言:老撾萬榮一對情侶失蹤青团,失蹤者是張志新(化名)和其女友劉穎譬巫,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體督笆,經(jīng)...
    沈念sama閱讀 45,696評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡芦昔,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,888評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了娃肿。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片咕缎。...
    茶點故事閱讀 40,013評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡珠十,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出凭豪,到底是詐尸還是另有隱情焙蹭,我是刑警寧澤,帶...
    沈念sama閱讀 35,731評論 5 346
  • 正文 年R本政府宣布嫂伞,位于F島的核電站孔厉,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏帖努。R本人自食惡果不足惜撰豺,卻給世界環(huán)境...
    茶點故事閱讀 41,348評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望拼余。 院中可真熱鬧污桦,春花似錦、人聲如沸姿搜。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,929評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽舅柜。三九已至,卻和暖如春躲惰,著一層夾襖步出監(jiān)牢的瞬間致份,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,048評論 1 270
  • 我被黑心中介騙來泰國打工础拨, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留氮块,地道東北人。 一個月前我還...
    沈念sama閱讀 48,203評論 3 370
  • 正文 我出身青樓诡宗,卻偏偏與公主長得像滔蝉,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子塔沃,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,960評論 2 355