摘要:當一個線程持有重量級鎖時,另外一個線程就會被直接踢到同步隊列中等待。
java代碼先編譯成字節碼,字節碼最后編譯成cpu指令,因此Java的多線程實現最終依賴于jvm和cpu的實現
synchronized和volatile我們先來討論一下volatile關鍵字的作用以及實現機制,每個線程看到的用volatile修飾的變量的值都是最新的,更深入的解釋就涉及到Java的內存模型了,我們知道Java將內存分為主內存和線程私有內存,所有的全局變量都在主內存中,每個線程使用變量時都會從主內存中讀取變量,然后放到各自線程的私有內存中,這樣線程使用變量時就不用每次都去讀取主內存了,當然這也產生了一個問題,如果線程修改了變量值,但是修改的值沒有及時地同步到主內存中,那么其他線程看到的變量值仍然是未修改之前的值,這就產生了并發問題,而當這個變量用volatile修飾后,每次線程都會從主內存中讀取變量值,也就是說拋棄了線程私有內存中的變量值,而線程每次修改變量后,就會將修改后的值同步到主內存中去。
理論上volatile就是這么實現滴,但是volatile最終會被編譯成機器指令,所以volatile這種機制也需要相關的機器指令支持,學習過計算機組成原理的同學們都知道計算機在cpu和主內存直接有一個cache緩存,是不是和Java模型很類似,當然還不一樣,其實volatile最終使用了cpu緩存一致性也就是說將緩存中的內容立刻更新到主內存中去,同時將其他緩存中的值置為無效。如果大家有探索精神可以看看看看volatile被編程為的匯編代碼,就會發現volatile是用Lock信號實現地。
下面我們再來說說synchronized關鍵字,學習過Java的同學應該都知道這個關鍵字是用來實現多線程同步的,synchronized的具體用法這里就不介紹了,我們來聊下這個關鍵字的具體實現,看過Java并發的同學都會發現synchronized被稱為重量級鎖,怎么理解這個重量級的概念那?反正我的理解是加鎖解鎖耗費地時間多,導致并發度比較低唄,但是隨著JDK版本的升級,synchronized的性能和并發庫中Lock的性能基本持平。好了言歸正傳,synchronized的具體實現不知道同學們了解多少,我想大部分人應該能說出synchronized由一個同步隊列和對象監視器實現,線程進入同步塊時,先獲取監視器如果成功就進入同步塊,如果不成功就進入同步隊列等待另外一個線程從同步塊退出,沒錯這就是synchronized的實現,如果你只知道這些說明你了解的還不夠深入,因為你還需要知道偏向鎖、輕量級鎖和synchronized的關系,在這里我就拋磚引玉先說說我自己的理解吧,我們都知道一個Java對象有三部分組成,對象頭,實體部分,對齊填充部分,這個對象頭就是實現synchronized的關鍵,在比較老的JDK版本中,一個線程進入同步代碼塊時就要獲取互斥量,不管有沒有其他線程,改進后的synchronized,線程一般先獲取偏向鎖,如果有競爭就膨脹為輕量級鎖或者重量級鎖,輕量級鎖又會膨脹為重量級鎖,那么偏向鎖、輕量級鎖、重量級鎖有什么區別那?
偏向鎖:
對象頭中設置偏向鎖標記,同時將當前線程的線程id保存在對象頭和棧的鎖記錄空間中;
輕量級鎖
將對象頭的內容復制到當前線程棧的鎖記錄空間中,同時將對象頭設置為指向鎖記錄空間的指針;
重量級鎖
將對象頭的內容復制到當前線程的鎖記錄空間中,同時將對象頭設置為指向互斥量的指針;
當一個線程進入同步快時,先通過cas設置對象頭為偏向鎖,若設置成功則說明線程獲取鎖,若設置不成功,說明鎖存在競爭,持有偏向鎖的線程就要釋放偏向鎖,偏向鎖膨脹為輕量級鎖或重量級鎖。
當一個線程持有輕量級鎖,另外一個線程嘗試獲取鎖,獲取失敗,則另外一個線程會自旋等待,若等待一段時間仍未獲取鎖,則線程進入等待,持有輕量級鎖的線程就會在安全點處釋放輕量級鎖,輕量級鎖也會膨脹為重量級鎖。
當一個線程持有重量級鎖時,另外一個線程就會被直接踢到同步隊列中等待。
(安全點是jvm的一些特殊位置,在這個位置上所有的線程都會暫停工作,一般在安全點處進行垃圾回收,還有一個概念是安全區域,安全區域是指在一塊代碼內引用關系不會發生變化,這個代碼的任何位置進行垃圾回收都是可以的)
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/71036.html
摘要:線程啟動規則對象的方法先行發生于此線程的每一個動作。所以局部變量是不被多個線程所共享的,也就不會出現并發問題。通過獲取到數據,放入當前線程處理完之后將當前線程中的信息移除。主線程必須在啟動其他線程后立即調用方法。 一、線程安全性 定義:當多個線程訪問某個類時,不管運行時環境采用何種調度方式,或者這些線程將如何交替執行,并且在主調代碼中不需要任何額外的同步或協同,這個類都能表現出正確的行...
摘要:所以接下來,我們需要簡單的介紹下多線程中的并發通信模型。比如中,以及各種鎖機制,均為了解決線程間公共狀態的串行訪問問題。 并發的學習門檻較高,相較單純的羅列并發編程 API 的枯燥被動學習方式,本系列文章試圖用一個簡單的栗子,一步步結合并發編程的相關知識分析舊有實現的不足,再實現邏輯進行分析改進,試圖展示例子背后的并發工具與實現原理。 本文是本系列的第一篇文章,提出了一個簡單的業務場景...
摘要:今天開始整理學習多線程的知識,談談最重要的兩個關鍵字和。但是這樣一個過程比較慢,在使用多線程的時候就會出現問題。有序性有序性是指多線程執行結果的正確性。這種機制在多線程中會出現問題,因此可以通過來禁止重排。 今天開始整理學習多線程的知識,談談最重要的兩個關鍵字:volatile和synchronized。 一、三個特性 1、原子性 所謂原子性操作就是指這些操作是不可中斷的,要么執行過程...
摘要:今天給大家總結一下,面試中出鏡率很高的幾個多線程面試題,希望對大家學習和面試都能有所幫助。指令重排在單線程環境下不會出先問題,但是在多線程環境下會導致一個線程獲得還沒有初始化的實例。使用可以禁止的指令重排,保證在多線程環境下也能正常運行。 下面最近發的一些并發編程的文章匯總,通過閱讀這些文章大家再看大廠面試中的并發編程問題就沒有那么頭疼了。今天給大家總結一下,面試中出鏡率很高的幾個多線...
摘要:線程的這種交叉操作會導致線程不安全。原子操作是在多線程環境下避免數據不一致必須的手段。如果聲明一個域為一些情況就可以確保多線程訪問到的變量是最新的。并發要求一個線程對對象進行了操作,對象發生了變化,這種變化應該對其他線程是可見的。 雖是讀書筆記,但是如轉載請注明出處 http://segmentfault.com/blog/exploring/ .. 拒絕伸手復制黨 一個問題: ...
閱讀 2164·2021-11-11 16:55
閱讀 1685·2019-08-30 15:54
閱讀 2817·2019-08-30 15:53
閱讀 2211·2019-08-30 15:44
閱讀 1152·2019-08-30 15:43
閱讀 965·2019-08-30 11:22
閱讀 1942·2019-08-29 17:20
閱讀 1566·2019-08-29 16:56