java語言

當前位置 /首頁/計算機/java語言/列表

java多執行緒同步塊例項講解素材

Java 同步塊(synchronized block)用來標記方法或者程式碼塊是同步的。Java 同步塊用來避免競爭。本文介紹以下內容:

java多執行緒同步塊例項講解素材

Java 同步關鍵字(synchronzied) 例項方法同步 靜態方法同步 例項方法中同步塊 靜態方法中同步塊 Java 同步示例

Java 同步關鍵字(synchronized)

Java 中的同步塊用 synchronized 標記。同步塊在 Java 中是同步在某個物件上。所有同步在一個物件上的同步塊在同時只能被一個執行緒進入並執行操作。所有其他等待進入該同步塊的執行緒將被阻塞,直到執行該同步塊中的執行緒退出。

有四種不同的同步塊:

例項方法 靜態方法 例項方法中的同步塊 靜態方法中的同步塊

上述同步塊都同步在不同物件上。實際需要那種同步塊視具體情況而定。

例項方法同步

下面是一個同步的例項方法:

public synchronized void add(int value){t += value; }

靜態方法同步

靜態方法同步和例項方法同步方法一樣,也使用 synchronized 關鍵字。Java 靜態方法同步如下示例:

public static synchronized void add(int value){ count += value; }

同樣,這裡 synchronized 關鍵字告訴 Java 這個方法是同步的。

靜態方法的同步是指同步在該方法所在的.類物件上。因為在 Java 虛擬機器中一個類只能對應一個類物件,所以同時只允許一個執行緒執行同一個類中的靜態同步方法。

對於不同類中的靜態同步方法,一個執行緒可以執行每個類中的靜態同步方法而無需等待。不管類中的那個靜態同步方法被呼叫,一個類只能由一個執行緒同時執行。

例項方法中的同步塊

有時你不需要同步整個方法,而是同步方法中的一部分。Java 可以對方法的一部分進行同步。

在非同步的 Java 方法中的同步塊的例子如下所示:

public void add(int value){ synchronized(this){ t += value; } }

示例使用 Java 同步塊構造器來標記一塊程式碼是同步的。該程式碼在執行時和同步方法一樣。

注意 Java 同步塊構造器用括號將物件括起來。在上例中,使用了“this”,即為呼叫 add 方法的例項本身。在同步構造器中用括號括起來的物件叫做監視器物件。上述程式碼使用監視器物件同步,同步例項方法使用呼叫方法本身的例項作為監視器物件。

一次只有一個執行緒能夠在同步於同一個監視器物件的 Java 方法內執行。

下面兩個例子都同步他們所呼叫的例項物件上,因此他們在同步的執行效果上是等效的。

public class MyClass { public synchronized void log1(String msg1, String msg2){ eln(msg1); eln(msg2); } public void log2(String msg1, String msg2){ synchronized(this){ eln(msg1); eln(msg2); } } }

在上例中,每次只有一個執行緒能夠在兩個同步塊中任意一個方法內執行。

如果第二個同步塊不是同步在 this 例項物件上,那麼兩個方法可以被執行緒同時執行。

靜態方法中的同步塊

和上面類似,下面是兩個靜態方法同步的例子。這些方法同步在該方法所屬的類物件上。

public class MyClass { public static synchronized void log1(String msg1, String msg2){ eln(msg1); eln(msg2); } public static void log2(String msg1, String msg2){ synchronized(s){ eln(msg1); eln(msg2); } } }

這兩個方法不允許同時被執行緒訪問。

如果第二個同步塊不是同步在 s 這個物件上。那麼這兩個方法可以同時被執行緒訪問。

Java 同步例項

在下面例子中,啟動了兩個執行緒,都呼叫 Counter 類同一個例項的 add 方法。因為同步在該方法所屬的例項上,所以同時只能有一個執行緒訪問該方法。

public class Counter{ long count = 0; public synchronized void add(long value){ t += value; } } public class CounterThread extends Thread{ protected Counter counter = null; public CounterThread(Counter counter){ ter = counter; } public void run() { for(int i=0; i<10; i++){ (i); } } } public class Example { public static void main(String[] args){ Counter counter = new Counter(); Thread threadA = new CounterThread(counter); Thread threadB = new CounterThread(counter); t(); t(); } }

建立了兩個執行緒。他們的構造器引用同一個 Counter 例項。 方法是同步在例項上,是因為 add 方法是例項方法並且被標記上 synchronized 關鍵字。因此每次只允許一個執行緒呼叫該方法。另外一個執行緒必須要等到第一個執行緒退出 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); t(); t(); } }

注意這兩個執行緒,threadA 和 threadB,不再引用同一個 counter 例項。CounterA 和 counterB 的 add 方法同步在他們所屬的物件上。呼叫 counterA 的 add 方法將不會阻塞呼叫 counterB 的 add 方法。

以上就是對Java 多執行緒同步塊的知識講解,後續繼續補充相關資料,謝謝大家對本站的支援!