1. 程式人生 > >java併發程式設計中的一些理解

java併發程式設計中的一些理解

1、java併發程式設計中需要注意的挑戰以及應對策略?

在java併發程式設計中,會遇到上下文切換死鎖等問題。要想減少上下文切換,主要有以下的方法:

  1. 無鎖併發程式設計,比如將資料的ID按照Hash演算法取模分段,不同的執行緒處理不同的段;
  2. CAS演算法;
  3. 使用最少執行緒;避免建立不必要的執行緒;
  4. 協成;在單執行緒中實現多工的排程,在單執行緒中維持多個任務間的切換。

避免死鎖的一些常用手段:

  1. 避免一個執行緒同時獲得多個鎖;
  2. 避免一個執行緒在鎖內同時佔用多個資源,一般來說一個鎖只佔用一個資源;
  3. 嘗試使用定時鎖,使用lock.tryLock(timeout)來替代使用內部鎖機制;
  4. 對於資料庫鎖,加鎖和解鎖必須在同一個資料庫連線中,否則就會出現解鎖失敗!

2、java併發機制的volatile和synchronized.

volatile是輕量級的synchronized,它在多處理器開發中保證了共享變數的”可見性”。
可見性的意思是當一個執行緒修改一個共享變數時,另外一個執行緒能讀到這個修改的值。
如果volatile變數修飾符使用恰當的話,他比synchronized的使用和執行成本更低,因為它不會引起執行緒上下文的切換和排程。

2.1 volatile的兩個實現原則:

1、Lock字首指令會引起處理器快取回寫到記憶體;
2、一個處理器的快取回寫到記憶體並導致其他處理器的快取無效。

2.2 synchronized

在Java 1.6中,鎖一共有4種狀態,級別從低到高依次是:無鎖狀態、偏向鎖狀態、輕量級鎖狀態和重量級鎖狀態,這幾個狀態會隨著競爭情況逐漸升級。*鎖可以升級,但是不能降級,目的是為了提高獲得鎖和釋放鎖的效率*。

2.3 鎖的優缺點和對比

這裡寫圖片描述

3、原子操作的實現原理

處理器提供匯流排鎖定快取鎖定兩個機制來保證複雜記憶體操作的原子性。
1、使用匯流排鎖保證原子性
所謂匯流排鎖就是使用處理器提供的一個LOCK#訊號,當一個處理器在總線上輸出此訊號時,其他處理器的請求將被阻塞住,那麼該處理器可以獨佔共享記憶體。匯流排鎖定把cpu和記憶體之間的通訊鎖住了,這也就是說在鎖定期間,其他處理器不能操作其他記憶體地址的資料,所以匯流排開銷就比較大。
2、使用快取鎖定保證原子性
所謂”快取鎖定”是指記憶體區域如果被快取在處理器的快取行中,並且在Lock操作期間被鎖定,那麼當它執行鎖操作回寫到記憶體時,處理器不在總線上宣告LOCK#訊號,而是修改內部的記憶體地址,並允許它的快取一致性機制來保證操作的原子性。


快取一致性機制會阻止同時修改由兩個以上處理器快取的記憶體區域資料,當其他處理器回寫已被鎖定的快取行的資料時,會使快取行無效。
但是有兩種情況下處理器不會使用快取鎖定。
第一種情況是:當操作的資料不能被快取在處理器內部,或操作的資料跨多個快取行時,則處理器會呼叫匯流排鎖定。
第二種情況是:有些處理器不支援快取鎖定。

4、java如何實現的原子性?

通過迴圈CAS方式實現的。
鎖機制保證了只有獲得鎖的執行緒才能操作鎖定的記憶體區域。JVM內部實現了很多種鎖機制,有偏向鎖、輕量級鎖和互斥鎖。有意思的是除了偏向鎖,JVM實現鎖的方式都用了迴圈CAS,即當一個執行緒想進入同步塊的時候使用迴圈CAS的方式來獲取鎖,當它退出同步塊的時候使用迴圈CAS釋放鎖。