面試復(fù)習(xí)-Java并發(fā)編程

1.Java內(nèi)存模型

Java內(nèi)存模型

JMM的內(nèi)存模型如圖所示屈暗,其規(guī)定了所有變量都存儲在主內(nèi)存中据沈,每條線程還有自己的工作內(nèi)存承边,工作內(nèi)存中保存了被該線程使用到的變量的主內(nèi)存副本拷貝律胀,線程對變量的所有操作,都必須在工作內(nèi)存中進行遇八。
三大特性:

  • 可見性:指當一個線程修改了共享變量的值瘦赫,其他線程能夠立即得知這個修改箕般。JMM是通過在變量修改后將新值同步回主內(nèi)存,在變量讀取前從主內(nèi)存刷新變量值來實現(xiàn)可見性的顽分。
  • 原子性:不可分割徐许,某個線程在做具體某個事務(wù)時,中間不可以被加塞或分割卒蘸,需要整體完整雌隅。
  • 有序性:在本線程內(nèi)觀察,所有操作都是有序的悬秉。在一個線程觀察另一個線程澄步,所有操作都是無序的冰蘑,無序是因為發(fā)生了指令重排序和泌。

2.volatitle

volatitle是jvm提供的輕量級的同步機制,保證可見性祠肥,但不保證完整性武氓,禁止指令重排,其并不是并發(fā)安全的仇箱。由于其只保證可見性县恕,在不符合以下兩條規(guī)則的場景中,仍然要通過加鎖來保證原子性:

  • 運算結(jié)果并不依賴變量的當前值剂桥,或者能夠確保只有單一的線程修改變量的值忠烛。
  • 變量不需要與其他的狀態(tài)變量共同參與不變約束。

可見性保證:volatile保證了修飾的共享變量在轉(zhuǎn)換為匯編語言時权逗,會加上一個lock為前綴的指令美尸,當CPU發(fā)現(xiàn)這個指令時,會立刻做以下兩件事:
1.將當前內(nèi)核中線程工作內(nèi)存中該共享變量刷新到主存
2.通知其他內(nèi)核里緩存的該共享變量內(nèi)存地址無效

3.狀態(tài)切換

Java語言定義了5種線程狀態(tài)斟薇,在任意一個時間點师坎,一個線程只能有且只有一種狀態(tài):

  • 新建(New):創(chuàng)建后尚未啟動的線程處于這種狀態(tài)
  • 運行(Runnable):處于此狀態(tài)的線程有可能正在執(zhí)行,也有可能正在等待著CPU給它分配時間
  • 無限期等待(Waiting):處于這種狀態(tài)的線程不會被CPU分配時間堪滨,它們要等待被其他線程喚醒胯陋。可通過以下方法無限期等待:
    1.沒有設(shè)置Timeout參數(shù)的Object.wait()
    2.沒有設(shè)置Timeout參數(shù)的Thread.join()
    3.LockSupport.park()方法
  • 限期等待(Timed Waiting):這種狀態(tài)下也不會被分配CPU時間袱箱,不過無須等待被喚醒遏乔,一段時間后會由系統(tǒng)自動喚醒。
  • 阻塞(Blocked):線程在等待著獲取到一個排他鎖发笔。
  • 結(jié)束(Terminated):已終止的線程狀態(tài)盟萨。

4.線程安全

當多個線程訪問一個對象時,如果不用考慮這些線程在運行時環(huán)境下的調(diào)度和交替執(zhí)行筐咧,也不需要進行額外的同步鸯旁,或者在調(diào)用方進行任何其他的協(xié)調(diào)操作噪矛,調(diào)用這個對象的行為都可以獲得正確的結(jié)果,那這個對象是線程安全的铺罢。

5.線程安全的實現(xiàn)方法

5.1 互斥同步

同步是指多個線程并發(fā)訪問共享數(shù)據(jù)時艇挨,保證共享數(shù)據(jù)在同一時刻只被一個(或者是一些,使用信號量的時候)線程使用韭赘。而互斥是實現(xiàn)同步的一種手段缩滨,臨界區(qū)、互斥量和信號量都是主要的互斥實現(xiàn)方式泉瞻。

  • synchronized
    synchronized是JVM實現(xiàn)的脉漏,可用于同步代碼塊,同步一個方法袖牙,同步一個類侧巨,同步一個靜態(tài)方法。JVM基于進入和退出Monitor對象來實現(xiàn)方法同步和代碼塊同步鞭达。代碼塊同步是使用monitorenter和monitorexit指令實現(xiàn)的司忱,而方法同步卻不是。
    Java的線程是映射到操作系統(tǒng)的原生線程智商的畴蹭,如果要阻塞或喚醒一個線程坦仍,都需要操作系統(tǒng)來幫忙完成,這就需要從用戶態(tài)切換到內(nèi)核態(tài)種叨襟,因此狀態(tài)轉(zhuǎn)換你需要耗費很多的處理器時間繁扎,所以synchronized是Java語言的一個重量級操作。
  • synchronized的優(yōu)化
  1. 自旋鎖:互斥同步進入阻塞狀態(tài)的開銷很大糊闽。自旋鎖讓一個線程請求一個共享數(shù)據(jù)的鎖的時候執(zhí)行忙循環(huán)一段時間梳玫,如果在這段時間能獲得鎖,就可以避免進入阻塞狀態(tài)墓怀。它只適用于共享數(shù)據(jù)鎖定狀態(tài)很短的情況汽纠。
  2. 鎖消除:被檢測出不可能存在競爭的共享數(shù)據(jù)的鎖進行消除。
  3. 鎖粗化:如果虛擬機探測到一系列連續(xù)的操作對同一個對象頻繁加鎖傀履,就會把加鎖的范圍擴展到整個操作序列的外部虱朵。
  4. 輕量級鎖:相對于傳統(tǒng)的重量級鎖而言,使用CAS操作來避免重量級鎖使用互斥量的開銷钓账。先采用CAS操作進行同步碴犬,如果CAS失敗了再改用互斥量來進行同步。
  5. 偏向鎖:讓第一個獲取鎖對象的進程梆暮,在這之后獲取該鎖就不再需要進行同步操作服协。當有另外一個鎖去嘗試獲取這個對象時,偏向狀態(tài)就宣告結(jié)束啦粹,此時恢復(fù)到無鎖狀態(tài)或輕量級鎖狀態(tài)偿荷。
  • ReentrantLock
    基本語法上和synchronized相似窘游,都是可重入鎖,但增加了一些高級功能跳纳,比如等待可中斷忍饰、可實現(xiàn)公平鎖、鎖可以綁定多個條件寺庄。

  • 二者的區(qū)別

  1. synchronized基于jvm實現(xiàn)艾蓝,ReentrantLock基于jdk實現(xiàn)
  2. ReentranLock是等待可中斷的,synchronized不是
  3. ReentranLock可實現(xiàn)公平鎖
  4. ReentranLock可綁定多個條件斗塘。
5.2 非阻塞同步

從處理問題的方式上說赢织,互斥同步屬于一種悲觀的并發(fā)策略,總是認為只要不去做正確的同步措施馍盟,就會出現(xiàn)問題于置,無論是否出現(xiàn)競爭,都要進行加鎖朽合。而樂觀鎖是先進行操作俱两,如果沒有其他線程競爭共享數(shù)據(jù),那么操作就成功了曹步。這種樂觀的并發(fā)策略不需要把線程掛起。

  • CAS
    比較并交換休讳。CAS指令有3個操作數(shù)讲婚,內(nèi)存地址V,舊的期望值A(chǔ)俊柔,新的值B筹麸。只有當V的值等于A,才把V的值更新為B雏婶。
  • JUC中的原子類
    例如AtomicInteger中就調(diào)用了Unsafe類的CAS操作物赶。其自增操作就是基于CAS實現(xiàn)的。
  • ABA
    如果一個變量初次讀取的時候是A值留晚,后來被改為了B酵紫,然后又被改回A,那CAS會誤認為它沒有改變過错维,這就會導(dǎo)致ABA問題奖地。JUC提供了一個帶有標記的原子引用類AtomicStampedReference來解決這個問題,它可以通過控制變量值的版本來保證CAS的正確性赋焕。

6.AQS(AbstractQueuedSynchronizer隊列同步器)

AQS是一個用來構(gòu)建鎖和同步器的框架参歹,ReentrantLock,Semaphore隆判,F(xiàn)utureTask等等均是基于AQS犬庇。其核心思想是僧界,如果被請求的共享資源空閑,則將當前請求資源的線程設(shè)置為有效的工作線程臭挽,并且將共享資源設(shè)置為鎖定狀態(tài)捎泻。如果被請求的共享資源被占用,需要一套線程阻塞等待以及喚醒時鎖分配的機制埋哟,這個機制是用CLH隊列鎖實現(xiàn)的笆豁,即將暫時獲取不到鎖的線程加入到隊列中。

CLH是一個虛擬的雙向隊列(不存在隊列實例赤赊,僅存在結(jié)點間的關(guān)聯(lián)聯(lián)系)闯狱。AQS將每條請求共享資源的線程封裝成一個CLH鎖隊列的一個結(jié)點來實現(xiàn)鎖的分配。

  • AQS定義兩種資源共享方式
    Exclusive(獨占):只有一個線程能執(zhí)行抛计,如可重入鎖
    Share(共享):多個線程同時執(zhí)行哄孤,如Semaphore/CountDownLatch。

同步器的設(shè)計是基于模板方法模式的吹截,也就是說瘦陈,使用者需要繼承同步器并重寫指定的方法。


同步器可重寫的方法
  • AQS組件
  1. Semaphone:允許多個線程同時訪問資源波俄。
  2. CountDownLatch:用來控制一個線程等待多個線程晨逝。維護了一個計數(shù)器 cnt,每次調(diào)用 countDown() 方法會讓計數(shù)器的值減 1懦铺,減到 0 的時候捉貌,那些因為調(diào)用 await() 方法而在等待的線程就會被喚醒。
  3. CyclicBarrier:用來控制多個線程互相等待冬念,只有當多個線程都到達時趁窃,這些線程才會繼續(xù)執(zhí)行。
  4. ReentrantReadWriteLock:讀寫鎖允許同時對某一資源進行讀

7.ThreadLocal

ThreadLocal對象可以提供線程局部變量急前,每個線程Thread擁有一份自己的副本變量醒陆,多個線程互不干擾。每個線程都有一個ThreadLocalMap裆针,其結(jié)構(gòu)類似HashMap刨摩,但ThreadLocalMap中沒有鏈表結(jié)構(gòu)。每一個ThreadLocal對象作為Map中的key据块,value為代碼中放入的值码邻。
其中的key為弱引用,發(fā)生GC后另假,key會被回收像屋,而value為強引用,不會被回收边篮,這個時候就可能導(dǎo)致內(nèi)存泄漏己莺。ThreadLocalMap的解決方法為再調(diào)用set()奏甫、get()、remove()方法的時候凌受,會清理掉key為Null的記錄阵子。

8.線程池

http://www.reibang.com/p/3f6eed342491

9.場景

  • 死鎖
    public static Object lock1=new Object();
    public static Object lock2=new Object();

    public static void main(String[] args) {

        Thread thread1=new Thread(()->{

            synchronized (lock1){

                System.out.println("Thread 1 get Lock 1");

                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }finally {
                    synchronized (lock2){
                        System.out.println("Thread 1 get Lock 2");
                    }
                }

            }

        });

        Thread thread2=new Thread(()->{

            synchronized (lock2){

                System.out.println("Thread 2 get Lock 2");

                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }finally {
                    synchronized (lock1){
                        System.out.println("Thread 2 get Lock 1");
                    }
                }

            }

        });

        thread1.start();
        thread2.start();


    }
  • 兩個線程交替打印A和B
    public static volatile boolean flag=true;

    public static void main(String[] args) {



        Thread thread1=new Thread(() -> {

            while (true){

                if (flag){
                    System.out.println("A");
                    flag=!flag;
                }

            }




        });
        Thread thread2=new Thread(() -> {

            while (true){

                if (!flag){
                    System.out.println("B");
                    flag=!flag;
                }

            }

        });

        thread1.start();
        thread2.start();


    }
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市胜蛉,隨后出現(xiàn)的幾起案子挠进,更是在濱河造成了極大的恐慌,老刑警劉巖誊册,帶你破解...
    沈念sama閱讀 223,126評論 6 520
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件领突,死亡現(xiàn)場離奇詭異,居然都是意外死亡案怯,警方通過查閱死者的電腦和手機君旦,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,421評論 3 400
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來嘲碱,“玉大人金砍,你說我怎么就攤上這事÷缶猓” “怎么了恕稠?”我有些...
    開封第一講書人閱讀 169,941評論 0 366
  • 文/不壞的土叔 我叫張陵,是天一觀的道長离咐。 經(jīng)常有香客問我谱俭,道長,這世上最難降的妖魔是什么宵蛀? 我笑而不...
    開封第一講書人閱讀 60,294評論 1 300
  • 正文 為了忘掉前任,我火速辦了婚禮县貌,結(jié)果婚禮上术陶,老公的妹妹穿的比我還像新娘。我一直安慰自己煤痕,他們只是感情好梧宫,可當我...
    茶點故事閱讀 69,295評論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著摆碉,像睡著了一般塘匣。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上巷帝,一...
    開封第一講書人閱讀 52,874評論 1 314
  • 那天忌卤,我揣著相機與錄音,去河邊找鬼楞泼。 笑死驰徊,一個胖子當著我的面吹牛笤闯,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播棍厂,決...
    沈念sama閱讀 41,285評論 3 424
  • 文/蒼蘭香墨 我猛地睜開眼颗味,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了牺弹?” 一聲冷哼從身側(cè)響起浦马,我...
    開封第一講書人閱讀 40,249評論 0 277
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎张漂,沒想到半個月后晶默,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,760評論 1 321
  • 正文 獨居荒郊野嶺守林人離奇死亡鹃锈,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,840評論 3 343
  • 正文 我和宋清朗相戀三年荤胁,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片屎债。...
    茶點故事閱讀 40,973評論 1 354
  • 序言:一個原本活蹦亂跳的男人離奇死亡仅政,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出盆驹,到底是詐尸還是另有隱情圆丹,我是刑警寧澤,帶...
    沈念sama閱讀 36,631評論 5 351
  • 正文 年R本政府宣布躯喇,位于F島的核電站辫封,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏廉丽。R本人自食惡果不足惜倦微,卻給世界環(huán)境...
    茶點故事閱讀 42,315評論 3 336
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望正压。 院中可真熱鬧欣福,春花似錦、人聲如沸焦履。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,797評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽嘉裤。三九已至郑临,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間屑宠,已是汗流浹背厢洞。 一陣腳步聲響...
    開封第一講書人閱讀 33,926評論 1 275
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人犀变。 一個月前我還...
    沈念sama閱讀 49,431評論 3 379
  • 正文 我出身青樓妹孙,卻偏偏與公主長得像,于是被迫代替她去往敵國和親获枝。 傳聞我的和親對象是個殘疾皇子蠢正,可洞房花燭夜當晚...
    茶點故事閱讀 45,982評論 2 361

推薦閱讀更多精彩內(nèi)容