Java 線程同步的方法



1. synchronized

    同步方法:public synchronized void save(){}

    注: synchronized關鍵字也可以修飾靜態方法,此時如果調用該靜態方法,將會鎖住整個類

    同步代碼塊:

    synchronized(object){ }

    注:同步是一種高開銷的操作,因此應該儘量減少同步的內容。 
    通常沒有必要同步整個方法,使用synchronized代碼塊同步關鍵代碼即可。 

2.使用特殊域變量(volatile)實現線程同步

    a.volatile關鍵字爲域變量的訪問提供了一種免鎖機制, 
    b.使用volatile修飾域相當於告訴虛擬機該域可能會被其他線程更新, 
    c.因此每次使用該域就要重新計算,而不是使用寄存器中的值 
    d.volatile不會提供任何原子操作,它也不能用來修飾final類型的變量 

3.使用重入鎖實現線程同步

    在JavaSE5.0中新增了一個java.util.concurrent包來支持同步。 
    ReentrantLock類是可重入、互斥、實現了Lock接口的鎖, 
    它與使用synchronized方法和快具有相同的基本行爲和語義,並且擴展了其能力

    ReenreantLock類的常用方法有:

        ReentrantLock() : 創建一個ReentrantLock實例 
        lock() : 獲得鎖 
        unlock() : 釋放鎖 
    注:ReentrantLock()還有一個可以創建公平鎖的構造方法,但由於能大幅度降低程序運行效率,不推薦使用 

  注:關於Lock對象和synchronized關鍵字的選擇: 
        a.最好兩個都不用,使用一種java.util.concurrent包提供的機制, 
            能夠幫助用戶處理所有與鎖相關的代碼。 
        b.如果synchronized關鍵字能滿足用戶的需求,就用synchronized,因爲它能簡化代碼 
        c.如果需要更高級的功能,就用ReentrantLock類,此時要注意及時釋放鎖,否則會出現死鎖,通常在finally代碼釋放鎖 

4.使用局部變量實現線程同步 
    如果使用ThreadLocal管理變量,則每一個使用該變量的線程都獲得該變量的副本, 
    副本之間相互獨立,這樣每一個線程都可以隨意修改自己的變量副本,而不會對其他線程產生影響。

 

    ThreadLocal 類的常用方法

    ThreadLocal() : 創建一個線程本地變量 
    get() : 返回此線程局部變量的當前線程副本中的值 
    initialValue() : 返回此線程局部變量的當前線程的"初始值" 
    set(T value) : 將此線程局部變量的當前線程副本中的值設置爲value

5.使用阻塞隊列實現線程同步

    BlockingQueue也是java.util.concurrent下的主要用來控制線程同步的工具。

    BlockingQueue有四個具體的實現類,根據不同需求,選擇不同的實現類
    1、ArrayBlockingQueue:一個由數組支持的有界阻塞隊列,規定大小的BlockingQueue,其構造函數必須帶一個int參數來指明其大     小.其所含的對象是以FIFO(先入先出)順序排序的。

    2、LinkedBlockingQueue:大小不定的BlockingQueue,若其構造函數帶一個規定大小的參數,生成的BlockingQueue有大小限制,若      不帶大小參數,所生成的BlockingQueue的大小由Integer.MAX_VALUE來決定.其所含的對象是以FIFO(先入先出)順序排序的。

    3、PriorityBlockingQueue:類似於LinkedBlockQueue,但其所含對象的排序不是FIFO,而是依據對象的自然排序順序或者是構造函       數的Comparator決定的順序。

   4、SynchronousQueue:特殊的BlockingQueue,對其的操作必須是放和取交替完成的


6.使用原子變量實現線程同步

   需要使用線程同步的根本原因在於對普通變量的操作不是原子的。

   在java的util.concurrent.atomic包中提供了創建了原子類型變量的工具類使用該類可以簡化線程同步。
   其中AtomicInteger 表可以用原子方式更新int的值,可用在應用程序中(如以原子方式增加的計數器),
   但不能用於替換Integer;可擴展Number,允許那些處理機遇數字類的工具和實用工具進行統一訪問。
   AtomicInteger類常用方法:
   AtomicInteger(int initialValue) : 創建具有給定初始值的新的AtomicInteger
   addAddGet(int dalta) : 以原子方式將給定值與當前值相加
   get() : 獲取當前值



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章