摘要:的關鍵字中的塊使用關鍵字進行標記。由于每個類只有一個類對象存在于中,因此全局同時只有一個線程能夠進入到同一個類的靜態同步方法中。同步代碼塊使這種期望成為可能。注意同步代碼塊如何在括號中接受一個對象。相同的實例被傳入兩個不同的線程實例中。
Java的synchronized塊標記一個方法或一個代碼塊為同步的。synchronized塊能用于防止出現競態條件。
Java的synchronized關鍵字java中的synchronized塊使用synchronized關鍵字進行標記。一個synchronized塊在某個對象上被同步。所有在某個對象上同步的synchronized塊同時只能有一個線程執行,所有其他試圖進入synchronized塊的線程被阻塞,知道進入synchronized塊的線程退出。
synchronized關鍵字能夠用于編輯4種不同類型的塊:
實例方法
靜態方法
實例方法中的代碼塊
靜態方法中的代碼塊
這些塊被同步在不同的對象上。哪種synchronized塊是你需要的取決于實際情況。
同步的實例方法這里有一個同步的實例方法:
public synchronized void add(int value) { this.count += value; }
注意這里在方法定義中使用synchronized關鍵字。這告訴Java方法是同步的。
Java中一個同步的實例方法同步在這個方法所在的實例(對象)上。因此,每個實例的同步方法同步在不同的對象上:擁有這個方法的實例。同時只有一個線程能在一個同步的實例方法上執行。如果多于一個實例存在,則一個線程一次能執行在每個實例的一個同步實例方法中,每個實例一個線程。
同步的靜態方法靜態方法被標記為synchronized就像實例方法一樣使用synchronized關鍵字。這里有一個同步的靜態方法:
public static synchronized void add(int value) { count += value; }
這里synchronized關鍵字告訴Java這個方法是同步的。
同步的靜態方法同步在方法所屬的類對象(如MyClass.class)上。由于每個類只有一個類對象存在于JVM中,因此全局同時只有一個線程能夠進入到同一個類的靜態同步方法中。
如果靜態同步方法位于不同的類中,則一個線程能夠在每個類的靜態同步方法中執行。每個類一個線程。
實例方法的同步代碼塊有時不必同步整個方法。有時更傾向于只同步一個方法中的一部分。Java同步代碼塊使這種期望成為可能。
這里有一個在非同步Java方法中的同步代碼塊:
public void add(int value) { synchronized(this) { this.count += value; } }
這個例子使用Java同步代碼塊使得一塊代碼可以被同步訪問。這塊代碼現在就好像是一個同步方法被執行。
注意Java同步代碼塊如何在括號中接受一個對象。在上面的例子中“this”被使用,也就是這個方法調用所在的實例。括號中的對象叫做「monitor object」。這段代碼被叫做同步在一個monitor object上。一個同步的實例方法使用它所屬的對象作為monitor object。
同時只有一個線程能執行在同步于相同monitor object上的Java代碼塊。
下面兩個例子都是同步在他們被調用的實例上,兩者等價:
public class MyClass { public synchronized void log1(String msg1, String msg2) { log.writeln(msg1); log.writeln(msg2); } public void log2(String msg1, String msg2) { synchronized(this) { log.writeln(msg1); log.writeln(msg2); } } }
同時只有一個線程能夠執行在上面兩個同步代碼塊之一上面。
可能會有代碼塊同步在非this對象上。
靜態方法中的同步代碼塊這些方法同步在方法所屬類的類對象上:
public class MyClass { public static synchronized void log1(String msg1, String msg2) { log.writeln(msg1); log.writeln(msg2); } public static void log2(String msg1, String msg2) { synchronized(MyClass.class) { log.writeln(msg1); log.writeln(msg2); } } }
可能會有代碼塊同步在非MyClass.class上。
synchronized例子這里有一個例子,啟動2個線程,每個線程都在同一個Counter對象上調用add方法。同時只有一個線程會調用同一個對象的add方法,因為這個方法被synchronized關鍵字修飾在它所屬的同一個實例上。
public class Counter { long count = 0; public synchronized void add(long value) { this.count += value } }
public class CounterThread extends Thread { protected Counter counter = null; public CounterThread(Counter counter) { this.counter = counter; } public void run() { for(int i = 0; i < 10; i++) { counter.add(i); } } }
public class Example { public static void main(String[] args) { Counter counter = new Counter(); Thread threadA = new CounterThread(counter); Thread threadB = new CounterThread(counter); threadA.start(); threadB.start(); } }
兩個線程被創建。相同的Counter實例被傳入兩個不同的線程實例中。Counter.add()方法在實例上同步,因為add方法是一個實例方法,并被標記為synchronized。因此同時只有一個線程能調用add()方法。另一個線程會等待第一個線程離開add()方法,然后執行。
如果兩個線程引用兩個不同的Counter實例,則同時調用add()方法不會有問題。調用是對于不同的對象,因此方法調用也同步在不同的對象上。因此調用不會被阻塞。
public class Example { public static void main(String[] args) { Counter counterA = new Counter(); Counter counterB = new Counter(); Thread threadA = new CounterThread(counterA); Thread threadB = new CounterThread(counterB); threadA.start(); threadB.start(); } }
助理這里的threadA和threadB不再引用同一個counter實例。counterA和counterB的add方法同步在各自所屬對象上。調用counterA的add()方法不會紫塞調用在counterB的add()方法。
Java的同步實用工具synchronized機制是Java的第一個用于同步訪問共享在多線程間的同步機制。synchronized機制現在看來不是很先進,這也就是為什么Java5推出了一組同步實用類幫助開發者實現更細粒度的同步控制。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/75949.html
摘要:轉載請備注地址多線程學習二將分為兩篇文章介紹同步方法另一篇介紹同步語句塊。如果兩個線程同時操作對象中的實例變量,則會出現非線程安全,解決辦法就是在方法前加上關鍵字即可。 轉載請備注地址: https://blog.csdn.net/qq_3433... Java多線程學習(二)將分為兩篇文章介紹synchronized同步方法另一篇介紹synchronized同步語句塊。系列文章傳送門...
摘要:基本元素機制需要幾個元素來配合,分別是臨界區對象及鎖條件變量以及定義在對象上的,操作。這個外部條件在機制中稱為條件變量。提供的機制,其實是,等元素合作形成的,甚至說外部的條件變量也是個組成部分。 monitor的概念 管程,英文是 Monitor,也常被翻譯為監視器,monitor 不管是翻譯為管程還是監視器,都是比較晦澀的,通過翻譯后的中文,并無法對 monitor 達到一個直觀的描...
摘要:關鍵字加到非靜態方法上持有的是對象鎖。線程和線程持有的鎖不一樣,所以和運行同步,但是和運行不同步。所以盡量不要使用而使用參考多線程編程核心技術并發編程的藝術如果你覺得博主的文章不錯,歡迎轉發點贊。 系列文章傳送門: Java多線程學習(一)Java多線程入門 Java多線程學習(二)synchronized關鍵字(1) java多線程學習(二)synchronized關鍵字(2) J...
摘要:本文對多線程基礎知識進行梳理,主要包括多線程的基本使用,對象及變量的并發訪問,線程間通信,的使用,定時器,單例模式,以及線程狀態與線程組。源碼采用構建,多線程這部分源碼位于模塊中。通知可能等待該對象的對象鎖的其他線程。 本文對多線程基礎知識進行梳理,主要包括多線程的基本使用,對象及變量的并發訪問,線程間通信,lock的使用,定時器,單例模式,以及線程狀態與線程組。 寫在前面 花了一周時...
閱讀 2259·2021-08-23 09:46
閱讀 908·2019-08-29 18:31
閱讀 1861·2019-08-29 17:04
閱讀 2446·2019-08-29 12:23
閱讀 1851·2019-08-26 14:05
閱讀 1074·2019-08-26 13:44
閱讀 3140·2019-08-26 12:23
閱讀 2199·2019-08-26 10:46