一起聊聊實現線程同步的那些方法

使用synchronized關鍵字

synchronized是最簡單和最常用的一種同步方法,只需要使用synchronized進行包裹,就可以實現代碼塊實現線程同步。synchronized可以修飾:類、變數,方法,靜態變數,靜態方法,代碼塊。

使用鎖

java.util.concurrent.locks定義了多種鎖,其中ReentrantLock,ReentrantReadWriteLock比較常用。鎖需要主動的添加lock和unloock,如果lock以後沒有正確的unlock(忘記unlock,被異常跳過等)則會導致死鎖。所以在使用鎖的時候一定要記得使用unlock,並且lock以後會存在拋出異常的情況,最好把unlock寫在finally代碼塊中。

Advertisements

synchronized和鎖的區別:

  • synchronized是關鍵字,而鎖都是具體的類。

  • synchronized直接包裹代碼快,不會出現忘記釋放鎖的情況。鎖需要自己管理lock和unlock,可能會出現鎖為被正確的釋放而導致死鎖的情況。

使用特殊域變數(volatile)

java編程語言允許線程訪問共享變數,為了確保共享變數能被準確和一致的更新,線程應該確保通過排它鎖單獨獲得這個變數。java語言提供了volatile,在某些情況下比鎖更加方便。如果一個欄位被聲明或volatile,java線程內存模型確保所有線程看到這個變數值是一致的。

volatile變數修飾符如果使用恰當的話,它比synchronized的使用和執行成本會更低,因為它不會引起線程上下文的切換和調度。

Advertisements

synchronized與volatile實現同步的區別:

  • synchronized是一個重量級的同步功能,會切換上下文。volatile是一個輕量級的同步功能,無需進行上下文的切換。

  • synchronized需要在不同線程中爭搶同一個鎖,會出現死鎖的情況,而volatile則不需要進行爭搶,也不會出現死鎖的情況。

直接使用線程安全的基礎類

  • java.util.concurrent包中定義了許多具有線程安全的類,如:ConcurrentHashMap等。在多線程環境可以直接使用這些類,而不需要自己處理線程同步相關的內容。

  • java.util.concurrent.atomic包中定義了許多具有原子性質的類型,它們的各種操作都具有原子性,所以在多線程中也可以放心大膽的使用。

使用線程局部變數來定義Runnable中的不需要共享的變數

每一個ThreadLocal能夠放一個線程級別的變數,可是它本身能夠被多個線程共享使用,並且又能夠達到線程安全的目的,這是因為單的認為不同線程中get到的對象是不一樣的)。

Advertisements

你可能會喜歡