實現線程同步的幾種方式


synchronized關鍵字修飾的方法實現同步

1.在方法級別  public synchronized ….

 

內置鎖會保護整個方法。在調用該方法前,需要獲得內置鎖,否則就處於阻塞狀態。

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

 

2.同步代碼塊   synchronized(對象){}

 


即有synchronized關鍵字修飾的語句塊。 

通常沒有必要同步整個方法,使用synchronized代碼塊同步關鍵代碼即可。

/**
             * 用同步代碼塊實現
             * 
             * @param money
             */
            public void save1(int money) {
                synchronized (this) {
                    account += money;
                }
            }

 

 

1.當synchronized作用在方法上的時候,鎖住的就是這個對象的實例 synchronized(this). 

2.當一個線程訪問synchronized(this) 同步塊時, 另一個線程仍然可以訪問當前對象內的非synchroinzed(this)同步塊代碼

3.同步是一個耗性能的操作,因此我們盡量減少同步的內容,最好不要加載整個方法上

 

3.給對象加鎖

當有一個明確的對象作為鎖時,就可以用類似下面這樣的方式寫程序。

public void method3(SomeObject obj)
{
   //obj 鎖定的對象
   synchronized(obj)
   {
      // todo
   }
}

 

用synchronized 給account對象加了鎖。這時,當一個線程訪問account對象時,其他試圖訪問account對象的線程將會阻塞,直到該線程訪問account對象結束。也就是說誰拿到那個鎖誰就可以運行它所控制的那段代碼。

 

 4.修飾一個靜態的方法

public synchronized static void method() {
   // todo
}

靜態方法是屬於類的而不屬於對象的。同樣的,synchronized修飾的靜態方法鎖定的是這個類的所有對象。

 

當synchronized修飾靜態方法的時候, 同步對象就是這個類的類對象

如代碼中的例子,當第一個線程進入method1的時候,需要占用TestReflection.class才能執行。

第二個線程進入method2的時候進去不,只有等第一個線程釋放了對TestReflection.class的占用,才能夠執行。 反推過來,第二個線程也是需要占用TestReflection.class。 那么TestReflection.class就是method2的同步對象。

 

5. 修飾一個類

class ClassName {
   public void method() {
      synchronized(ClassName.class) {
         // todo
      }
   }
}

給class加鎖和上例的給靜態方法加鎖是一樣的,所有對象公用一把鎖

第二種:(volatile)實現線程同步 

volatile關鍵字為域變量的訪問提供了一種免鎖機制

只需在account前面加上volatile修飾,即可實現線程同步。

class Bank {
            //需要同步的變量加上volatile
            private volatile int account = 100;

            public int getAccount() {
                return account;
            }
            //這里不再需要synchronized 
            public void save(int money) {
                account += money;
            }
        }

1.多線程中的非同步問題主要出現在對域的讀寫上,如果讓域自身避免這個問題,則就不需要修改操作該域的方法。

2.volatile不能保證原子操作,因此volatile不能代替synchronized

3.每次要線程要訪問volatile修飾的變量時都是從內存中讀取,而不是從緩存當中讀取,因此每個線程訪問到的變量值都是一樣的。這樣就保證了同步。

java.util.concurrent包來支持同步


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM