Java安全執行緒,java線程

來源:互聯網
上載者:User

Java安全執行緒,java線程

  最近做筆試題,遇到了不少關於安全執行緒的題目,比如:

  synchronized和volatile的區別是什嗎?

  StringBuilder和StringBuffer的區別是什嗎?

  HashMap和HashTable的區別是什嗎?等等......

  這些問題的答案涉及到的,就是關於安全執行緒問題。首先先要對安全執行緒有個概念,怎樣才叫安全執行緒。

安全執行緒和線程不安全:

  安全執行緒指的是多個線程並發執行的時候,當一個線程訪問該類的某個資料的時候,通過加鎖的機制,保護資料,直至當前線程讀取完,釋放鎖後,其他線程才能繼續使用,我們認為這樣是安全執行緒的。

  有安全執行緒,自然就有線程不安全,線程不安全指的是,多個線程並發執行的時候,資料沒有得到保護,可能會出現多個線程修改或使用某個資料,導致所得到的資料不正確,也就是髒資料。

 

  瞭解完基本概念後,接下來要引用某大神從Java記憶體模型和線程同步機制方面來描述線程的安全性。

Java記憶體模型

  不同的平台,記憶體模型是不一樣的,但是jvm的記憶體模型規範是統一的。其實java的多線程並發問題最終都會反映在java的記憶體模型上,所謂安全執行緒無 非是要控制多個線程對某個資源的有序訪問或修改。總結java的記憶體模型,要解決兩個主要的問題:可見度和有序性。 

  可見度: 多個線程之間是不能互相傳遞資料通訊的,它們之間的溝通只能通過共用變數來進行。Java記憶體模型(JMM)規定了jvm有主記憶體,主記憶體是多個線程共用 的。當new一個對象的時候,也是被分配在主記憶體中,每個線程都有自己的工作記憶體,工作記憶體儲存了主存的某些對象的副本,當然線程的工作記憶體大小是有限制 的。當線程操作某個對象時,執行順序如下:

 (1) 從主存複製變數到當前工作記憶體 (read and load)
 (2) 執行代碼,改變共用變數值 (use and assign)
 (3) 用工作記憶體資料重新整理主存相關內容 (store and write)

  當一個共用變數在多個線程的工作記憶體中都有副本時,如果一個線程修改了這個共用 變數,那麼其他線程應該能夠看到這個被修改後的值,這就是多線程的可見度問題。
  有序性:線程在引用變數時不能直接從主記憶體中引用,如果線程工作記憶體中沒有該變數,則會從主記憶體中拷貝一個副本到工作記憶體中,完成後線程會引用該副本。當同一線程再度引用該欄位時,有可能重新從主存中擷取變數副本(read-load-use),也有可能直接引用原來的副本 (use),也就是說 read,load,use順序可以由JVM實現系統決定。
        線程不能直接為主存中欄位賦值,它會將值指定給工作記憶體中的變數副本(assign),完成後這個變數副本會同步到主儲存區(store- write),至於何時同步過去,根據JVM實現系統決定.有該欄位,則會從主記憶體中將該欄位賦值到工作記憶體中,這個過程為read-load,完成後線 程會引用該變數副本。

  舉個例子1,現有一變數x=10,a線程執行x=x+1操作,b線程執行x=x-1操作,倆線程同時啟動並執行時候,x的值是不確定的,有可能為9,也有可能為11,這就是多線程並發執行的順序是不可預見導致的,所以要使安全執行緒,要保證a線程和b線程的有序執行,且執行的操作必須為原子操作

  原子操作:在多線程訪問共用資源時,能夠確保所有其他的進程(線程)都不在同一時間內訪問相同的資源。原子操作(atomic operation)是不需要synchronized,這是Java多線程編程的老生常談了。所謂原子操作是指不會被線程調度機制打斷的操作;這種操作一旦開始,就一直運行到結束,中間不會有任何 context switch (切換到另一個線程)。

 

那麼如何確保線程執行的有序性和可見度呢?

synchronized關鍵字

  synchronized關鍵字可以解決有序性和可見度的問題,它保證了多個線程之間是互斥的,當一段代碼會修改共用變數,這一段代碼成為互斥區或 臨界區,為了保證共用變數的正確性,synchronized標示了臨界區。

  常用用法:

Java代碼  

synchronized(lock) {臨界區代碼}//例如:public synchronized void method() {}public static synchronized void method() {}

  無論synchronized關鍵字是加在方法還是對象中,都是取對象當作鎖,理論上每個對象都可以是一個鎖。

  對於public synchronized void method()這種情況,鎖就是這個方法所在的對象。同理,如果方法是public  static synchronized void method(),那麼鎖就是這個方法所在的class。

  synchronized關鍵字有兩種鎖對象,一種是對象加鎖,另一種是對類加鎖,對類加鎖,則類鎖對類裡的所有對象都起作用,而對象鎖只是針對該類的一個指定的對象加鎖,這個類的其它對象仍然可以使用已經對前一個對象加鎖的synchronized方法。

  例如:車站只剩一張票,A業務員和B業務員同時出票,執行public synchronized void sell()方法,那麼結果就會出現,剩餘票數為(-1)的情況,這就是對象鎖導致的問題,其他對象仍然可以使用這個方法;

  當把sell方法加上static後,鎖的對象就是這個類,對於A業務員和B業務員來說,都要按順序來操作業務,這樣就不會出現剩餘票數為負數的輕卡UN個了。

  當一個對象是鎖的時候,應該要被多個線程共用才是有意義的。這也得出一個結論:非安全執行緒!=不安全。

  比如ArrayList就是線程不安全的,但是並非說多線程情況下就不用ArrayList,如果你的每一個線程都new了一個ArrayList對象,也就是對象是非共用的,線程之間不存在資源競爭,那麼多線程執行的時候也是沒有安全問題的。

  每個鎖對象都有兩個隊列,一個是就緒隊列,一個是阻塞隊列,就緒佇列儲存體了將要獲得鎖的線程,阻塞佇列儲存體了被阻塞的線程,當一個線程被喚醒 後,才會進入到就緒隊列,等待cpu的調度。

  一個線程執行臨界區代碼過程如下:
  1 獲得同步鎖
  2 清空工作記憶體
  3 從主存拷貝變數副本到工作記憶體
  4 對這些變數計算
  5 將變數從工作記憶體寫回到主存
  6 釋放鎖
  可見,synchronized既保證了多線程的並發有序性,又保證了多線程的記憶體可見度。

  生產者/消費者模式就是典型的同步鎖問題,多線程執行過程除了操作是互斥的以外,往往也會出現線程之間互相協作的情況。

  比方說,A機器人負責造車子,造好了車子,就放在倉庫裡,倉庫每次只能放一輛車。

  (1)起初,A機器人被運行,執行造車子make方法,造好了車子放在倉庫後,沒有馬上關機(釋放鎖),而是喚醒了(notify)準備上班的(阻塞隊列)B機器人,自己再下班(進入阻塞隊列)

  (2)B機器人獲得同步鎖,上班,開始把造好的車子運出倉庫拿去出售,車子運出去後,它也沒有馬上溜了,而是喚醒了剛下班的A機器人繼續造車子(赤裸裸的剝削,我也要賣車子)。

  (3)A機器人發現倉庫的車子被運走了,接到任務就只能繼續開始造車子,造好車子把B機器人叫回來。

  (4)B機器人賣車子,叫醒A機器人造車子。

  。。。。。。

  可以看出,在同步鎖的作用下,造車子,賣車子,造車子,賣車子可以有序的進行,很愉快。

 

接下來要說的是另外一個關鍵字:volatile

volatile關鍵字

  volatile同樣也是Java同步的一種方法,只不過和synchronized鎖相比,稍弱了點,它只能保證多線程執行的可見度,可不能保證有序性。

  它的原理是不需要從主記憶體中複製一份副本到工作記憶體,而是直接對主記憶體的資料進行修改,這樣,其他線程都能立馬看到資料的修改。因此,volatile的使用範圍要臂synchronized小,常用於直接賦值的情況,諸如例子1的情況就是不適用的。

 

最後需要注意的是,synchronized鎖雖好,但是不能多用,會影響執行效率,阻塞隊列的線程也會不斷地嘗試擷取鎖,消耗效能。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.