并發(fā)相關知識點整理

并發(fā)稚失,即一個代碼塊同時被多個線程執(zhí)行搀绣,代碼塊中的變量會被同時的線程修改成不同的值飞袋,造成數據錯亂,運行結果錯誤現(xiàn)象產生链患,如何來避免這一問題產生呢巧鸭?這就產生了鎖機制,通過對代碼塊加鎖麻捻,來保證同一時刻只能有一個線程來操作數據纲仍,這樣就能保證數據的一致性。

一贸毕、鎖機制

  • 重入鎖/不可重入鎖
  • 共享鎖/互斥鎖
  • 樂觀鎖/悲觀鎖
  • 自旋鎖

重入鎖/不可重入鎖

在同一個線程中郑叠,可重復進入的鎖,就可重入鎖明棍。如乡革,一個線程中進入了一個帶鎖的方法,再次進入使用同一個鎖的其他方法時摊腋,不需要再獲取鎖沸版,可直接進入。

可重入鎖

  • ReentrantLock
  • synchronized

不可重入鎖

  • NoReentrantLock

共享鎖/互斥鎖

當一個線程獲取到鎖后兴蒸,其他線程也可以獲取此鎖视粮,則此鎖是共享鎖,如讀鎖橙凳;如果其他線程不能獲取此鎖蕾殴,則此鎖是互斥鎖,如寫鎖

  • ReentrantReadWriteLock

樂觀鎖/悲觀鎖

樂觀鎖認為并發(fā)操作一定會修改數據痕惋;悲觀鎖認為并發(fā)操作不會修改數據,但在寫數據時一般

樂觀鎖

  • AtomickInteger
  • AtomickXXX

悲觀鎖

  • ReentrantLock
  • synchronized

自旋鎖

一般情況下線程在未獲取到鎖的情況下會被阻塞娃殖,而自旋鎖則是內部有一個循環(huán)體在輪詢鎖是否可用值戳。自旋鎖可以減少線程上下文切換帶來的消耗,但會消耗CPU炉爆。

  • AtomicInteger
  • AtomicXXXX

二堕虹、死鎖

線程都要獲取鎖才能進行運行卧晓,但所有的線程都獲取不到,導致出現(xiàn)所有線程都不能運行的情況赴捞,這種情況就叫作死鎖逼裆。

死鎖場景

1. 設計不當

線程內有多個鎖,一個線程在獲取鎖A后赦政,需要再次獲取鎖B才能執(zhí)行相關代碼胜宇,而此刻另一線程已經獲取到鎖B,但它卻在等待獲取鎖A來執(zhí)行代碼恢着,兩個線程都要獲取對方已經獲取到的鎖桐愉,而又都獲取不到,造成死循環(huán)掰派,也就是死鎖現(xiàn)象从诲。

2. 程序異常

線程在獲取鎖后執(zhí)行相關代碼,執(zhí)行完相關代碼后釋放鎖靡羡。但執(zhí)行過程發(fā)生了異常系洛,導致線程意外退出,獲取到的鎖沒有被釋放略步,導致其他所有線程都無法獲取鎖的情況描扯。
解決方案:添加try/catch,在finally塊里釋放鎖

class AClass{
    ReentrantLock lock=new ReentrantLock();
    
    void aMethod() {
        lock.lock();
        try {
            doSomeThing();
        } catch(Throwable e){
            e.printStacktrace();
        } finally {      
            lock.unlock();
        }
    }
}

三纳像、synchronized使用方式

synchronized可根據加鎖范圍分為以下兩種方式荆烈,但

  • 鎖對象
  • 鎖類

鎖對象

即針對對象中的方法進行加鎖,一個對象的加鎖方法被線程進入后竟趾,其他線程不能再進入此對象加鎖的方法憔购,但可以進入不同對象的同一加鎖方法。

  1. synchronized修飾普通方法
public synchronized void test1(){
    ...
}
  1. synchronized代碼塊岔帽,內部使用this或成員變量
public void test1(){
    synchronized(this){
        ...
    }
}

鎖類

類鎖與對象鎖是一致的玫鸟,但類方法在內存中只有一份。加鎖的是整個類方法犀勒,當一個線程獲取到類方法鎖后屎飘,其他線程不能再進入此方法。

  1. synchronized修飾靜態(tài)方法
public synchronized static void test1(){
    ....
}
  1. synchronized代碼塊贾费,內部使用class
public void test1(){
    synchronized(Test.class){
        ...
    }
}

四钦购、鎖機制單例中的應用

單例對并發(fā)方面的考慮主要是

  1. 防止創(chuàng)建多個對象。單例要求全局只有一個對象
  2. 防止單例對象中的數據被并發(fā)修改造成錯誤

創(chuàng)建方式

1. 懶漢模式

需要時再創(chuàng)建

class ConnectionManager{

    private static ConnectionManager sInstance = new ConnectionManager();
    
    private ConnectionManager(){
        
    }
    
    /**
     * 此方式每次獲取都會加鎖褂萧,目的是防止創(chuàng)建多個對象押桃,
     * 但創(chuàng)建對象只有一次,其他都是獲取导犹,造成性能損耗
     */
    public synchronized static ConnectionManager getInstance(){
        if(sInstance==null){
            sInstance=new ConnectionManager();
        }
        return sInstance;
    }
}

2. 餓漢模式

直接初始化(太饑餓唱凯,上來就直接吃)

public class ConnectionManager{

    private static ConnectionManager sInstance = new ConnectionManager();
    
    private ConnectionManager(){
    }
    
    public static ConnectionManager getInstance(){
        return sInstance;
    }
} 

3. 雙重檢測

a. 為什么要2次null判斷羡忘?   
    防止兩個線程同時進入第一個if模塊,當一個線程獲取鎖后創(chuàng)建一個對象磕昼;在它釋放鎖后卷雕,另一個線程獲取到鎖,又創(chuàng)建一個對象票从。   
b. 為什么使用volatile修飾漫雕?   
    防止指令重排問題。sInstance=new ConnectionManager();這句代碼并不是原子操作纫骑,它有三條指令:分配內存蝎亚、初始化內存、賦值變量先馆。如果先賦值后初始化发框,就可能會出現(xiàn)另一線程在第一個null判斷時,發(fā)現(xiàn)不為空煤墙,直接使用對象的情況梅惯,而此時對象可能還沒被初始化造成錯誤。
class ConnectionManager{
    private volatile static ConnectionManager sInstance = null;
    private ConnectionManager(){
        
    }
    
     public static ConnectionManager getInstance(){
        if(sInstance==null){
            synchronized(ConnectionManager.class){
                if(sInstance==null){
                    sInstance=new ConnectionManager();
                }
            }
        }
        return sInstance;
    }
}

4. 靜態(tài)內部類

class ConnectionManager{

    private ConnectionManager(){
        
    }
    
    public static ConnectionManager getInstance(){
        return Holder.INSTANCE;
    }

    private static class Holder{
        private final static ConnectionManager INSTANCE = new ConnectionManager();
    }
}

5. 枚舉

enum ConnectionManager{
    INSTANCE;
    private ConnectionManager(){
        
    }
}  

五仿野、進程通信

  • binder
  • 管道
  • 廣播
  • 文件
  • socket

生產者消費者機制

信息號機制

六铣减、線程安全相關類

容器類

  • ConcurentHashMap
  • CopyOnWriteArrayList
  • CopyOnWriteArraySet
  • LinkedBlockingList
  • LinkedBlockingQueue
  • Vector
  • HashTable
  • Collections.synchronizedList(new ArrayList<T>());
  • Collections.synchronizedSet(new HashSet<T>());
  • Collections.synchronizedMap(new HashMap<String,String>());

字符串類

  • StringBuffer

參考

https://zhuanlan.zhihu.com/p/52563959

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市脚作,隨后出現(xiàn)的幾起案子葫哗,更是在濱河造成了極大的恐慌,老刑警劉巖球涛,帶你破解...
    沈念sama閱讀 217,509評論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件劣针,死亡現(xiàn)場離奇詭異,居然都是意外死亡亿扁,警方通過查閱死者的電腦和手機捺典,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,806評論 3 394
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來从祝,“玉大人襟己,你說我怎么就攤上這事‰鼓埃” “怎么了擎浴?”我有些...
    開封第一講書人閱讀 163,875評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長毒涧。 經常有香客問我贮预,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,441評論 1 293
  • 正文 為了忘掉前任萌狂,我火速辦了婚禮,結果婚禮上怀泊,老公的妹妹穿的比我還像新娘茫藏。我一直安慰自己,他們只是感情好霹琼,可當我...
    茶點故事閱讀 67,488評論 6 392
  • 文/花漫 我一把揭開白布务傲。 她就那樣靜靜地躺著,像睡著了一般枣申。 火紅的嫁衣襯著肌膚如雪售葡。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,365評論 1 302
  • 那天忠藤,我揣著相機與錄音挟伙,去河邊找鬼。 笑死模孩,一個胖子當著我的面吹牛尖阔,可吹牛的內容都是我干的。 我是一名探鬼主播榨咐,決...
    沈念sama閱讀 40,190評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼介却,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了块茁?” 一聲冷哼從身側響起齿坷,我...
    開封第一講書人閱讀 39,062評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎数焊,沒想到半個月后永淌,有當地人在樹林里發(fā)現(xiàn)了一具尸體,經...
    沈念sama閱讀 45,500評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡昌跌,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,706評論 3 335
  • 正文 我和宋清朗相戀三年仰禀,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蚕愤。...
    茶點故事閱讀 39,834評論 1 347
  • 序言:一個原本活蹦亂跳的男人離奇死亡答恶,死狀恐怖,靈堂內的尸體忽然破棺而出萍诱,到底是詐尸還是另有隱情悬嗓,我是刑警寧澤,帶...
    沈念sama閱讀 35,559評論 5 345
  • 正文 年R本政府宣布裕坊,位于F島的核電站包竹,受9級特大地震影響,放射性物質發(fā)生泄漏。R本人自食惡果不足惜周瞎,卻給世界環(huán)境...
    茶點故事閱讀 41,167評論 3 328
  • 文/蒙蒙 一苗缩、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧声诸,春花似錦酱讶、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,779評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至慰照,卻和暖如春灶挟,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背毒租。 一陣腳步聲響...
    開封第一講書人閱讀 32,912評論 1 269
  • 我被黑心中介騙來泰國打工稚铣, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人墅垮。 一個月前我還...
    沈念sama閱讀 47,958評論 2 370
  • 正文 我出身青樓榛泛,卻偏偏與公主長得像,于是被迫代替她去往敵國和親噩斟。 傳聞我的和親對象是個殘疾皇子曹锨,可洞房花燭夜當晚...
    茶點故事閱讀 44,779評論 2 354

推薦閱讀更多精彩內容

  • 面試發(fā)現(xiàn)經常有些重復的面試問題,自己也應該學會記錄下來剃允,最好自己能做成筆記沛简,在下一次面的時候說得有條不紊,深入具體...
    SunShine_skay閱讀 351評論 0 0
  • 簡介 整理容器的基本知識 整理關于不同容器線程安全方面的知識 根據以下資料整理 http://www.jiansh...
    千葉鳥閱讀 433評論 0 1
  • 導讀:記錄下java中提供鎖的兩種方式:synchronized和Lock(juc里面提供的鎖) 一斥废、問題的產生和...
    Toyouy閱讀 338評論 0 0
  • 一椒楣、知識結構分析 多線程之間的關系 pthread是POSIX線程的API NSThread是Cocoa對pthr...
    huoshe2019閱讀 479評論 0 4
  • iOS中多線程 首先看一道面試題 iOS中多線程有哪些實現(xiàn)方案? iOS中牡肉,多線程一般有三種方案GCD捧灰、NSOpe...
    木子奕閱讀 652評論 0 1