本文介紹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中文網!