首頁 >Java >java教程 >java多執行緒程式設計之Synchronized關鍵字詳解

java多執行緒程式設計之Synchronized關鍵字詳解

高洛峰
高洛峰原創
2017-01-05 14:43:381519瀏覽

本文介紹JAVA多執行緒中的synchronized關鍵字作為物件鎖的一些知識點。

所謂物件鎖,就是就是synchronized 給某個物件 加鎖。關於 物件鎖定 可參考:這篇文章

 一、分析

synchronized可以修飾實例方法,如下形式:

public class MyObject {
  synchronized public void methodA() {
    //do something....
  }

   

這裡,synchronized 鎖定的是當前物件。這也是稱為物件鎖的原因。

為啥鎖住當前物件?因為methodA()是個實例方法,要執行methodA(),需要以對象.方法() 的形式進行呼叫(obj.methodA(),obj是MyObject類別的一個對象,synchronized就是把obj這個物件加鎖了)。

上面程式碼也可寫成這樣:

public class MyObject {
 
  public void methodA() {
    synchronized(this){
      //do something....
    }
  }

   

二、特點

使用synchronized關鍵字同步一個明顯的特點是:MyObject類別中定義有多個synchronized擁有同一個MyObject類別的對象,則這些方法只能以同步的方式執行。即,執行完一個synchronized修飾的方法後,才能執行另一個synchronized修飾的方法。

如下:

public class MyObject {
 
  synchronized public void methodA() {
    //do something....
  }
 
  synchronized public void methodB() {
    //do some other thing
  }
}

   

MyObject類別中有兩個synchronized修飾的方法。

public class ThreadA extends Thread {
 
  private MyObject object;
//省略构造方法
  @Override
  public void run() {
    super.run();
    object.methodA();
  }
}

   

線程A執行methodA()

public class ThreadB extends Thread {
 
  private MyObject object;
//省略构造方法
  @Override
  public void run() {
    super.run();
    object.methodB();
  }
}

   

B Object類別的物件object,儘管這兩個執行緒需要呼叫不同的方法,但是必須是同步的,例如:執行緒B需要等待執行緒A執行完了methodA()方法之後,它才能執行methodB()方法。

 三、結論

從上可以看出,本文中講述的 synchronized 鎖的範圍是整個物件。如果一個類別中有多個synchronized修飾的同步方法,且多個執行緒持有該類別的同一個物件(該類別的相同的物件),儘管它們呼叫不同的方法,各個方法的執行也是同步的。

如果各個同步的方法之間沒有共享變量,或者說各個方法之間沒有聯繫,但也只能同步執行,這會影響效率。

四、應用--使用synchronized避免 因資料不一致性而導致讀取髒資料的情況

如下範例:

public class Run {
  public static void main(String[] args) {
    MyObject object = new MyObject();
 
    //线程A与线程B 持有的是同一个对象:object
    ThreadA a = new ThreadA(object);
    ThreadB b = new ThreadB(object);
    a.start();
    b.start();
  }
}

   

methodA()負責更改使用者名稱和密碼。在現實中,一個使用者名稱對應著一個密碼。

methodB()負責讀取使用者名稱和密碼。

如果methodB()沒有用synchronized 修飾,線程A在呼叫methodA()執行到第7行,更改了用戶名,因某種原因(例如在第9行睡眠了)放棄了CPU。

此時,如果線程B去執行methodB(),那麼讀取到的用戶名是線程A更改了的用戶名("a"),但是密碼卻是原來的密碼("bb")。因為,線程A睡眠了,還來不及更改密碼。

但是,如果methodB()用synchronized修飾,那麼線程B只能等待線程A執行完畢之後(即改了用戶名,也改了密碼),才能執行methodB讀取用戶名和密碼。因此,就避免了數據的不一致性而導致的髒讀問題。

以上就是本文的全部內容,希望對大家學習java程式設計有所幫助。

更多java多執行緒程式設計之Synchronized關鍵字詳解相關文章請關注PHP中文網!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn