Java中的synchronized關鍵字
當我們在程式中啟動兩個或多個執行緒時,可能出現多個執行緒試圖訪問同一資源的情況,最終由於併發問題而產生不可預測的結果。例如,如果多個執行緒試圖寫入同一個檔案,則它們可能會損壞資料,因為其中一個執行緒可能會覆蓋資料,或者當一個執行緒正在開啟同一個檔案時,另一個執行緒可能正在關閉同一個檔案。
因此,需要同步多個執行緒的操作,並確保在給定時間點只有一個執行緒可以訪問資源。這是使用稱為**監視器**的概念實現的。Java中的每個物件都與一個監視器關聯,執行緒可以鎖定或解鎖該監視器。一次只有一個執行緒可以持有監視器的鎖。
Java程式語言提供了一種非常方便的方法來建立執行緒並使用**synchronized**塊同步其任務。您可以將共享資源保留在此塊中。以下是synchronized語句的一般形式:
語法
synchronized(objectidentifier) { // Access shared variables and other shared resources }
這裡,**objectidentifier** 是對物件的引用,其鎖與synchronized語句表示的監視器相關聯。現在我們將看到兩個示例,我們將使用兩個不同的執行緒列印計數器。當執行緒不同步時,它們列印的計數器值不是按順序的,但是當我們將計數器放在synchronized()塊內列印時,它會為兩個執行緒按順序列印計數器。
無同步的多執行緒示例
這是一個簡單的示例,它可能按順序列印計數器值,也可能不按順序列印計數器值,並且每次執行它時,它都會根據CPU對執行緒的可用性產生不同的結果。
示例
class PrintDemo { public void printCount() { try { for(int i = 5; i > 0; i--) { System.out.println("Counter --- " + i ); } } catch (Exception e) { System.out.println("Thread interrupted."); } } } class ThreadDemo extends Thread { private Thread t; private String threadName; PrintDemo PD; ThreadDemo( String name, PrintDemo pd) { threadName = name; PD = pd; } public void run() { PD.printCount(); System.out.println("Thread " + threadName + " exiting."); } public void start () { System.out.println("Starting " + threadName ); if (t == null) { t = new Thread (this, threadName); t.start (); } } } public class TestThread { public static void main(String args[]) { PrintDemo PD = new PrintDemo(); ThreadDemo T1 = new ThreadDemo( "Thread - 1 ", PD ); ThreadDemo T2 = new ThreadDemo( "Thread - 2 ", PD ); T1.start(); T2.start(); // wait for threads to end try { T1.join(); T2.join(); } catch ( Exception e) { System.out.println("Interrupted"); } } }
每次執行此程式都會產生不同的結果:
輸出
Starting Thread - 1 Starting Thread - 2 Counter --- 5 Counter --- 4 Counter --- 3 Counter --- 5 Counter --- 2 Counter --- 1 Counter --- 4 Thread Thread - 1 exiting. Counter --- 3 Counter --- 2 Counter --- 1 Thread Thread - 2 exiting.
帶同步的多執行緒示例
這是同一個示例,它按順序列印計數器值,並且每次執行它時,它都會產生相同的結果。
示例
class PrintDemo { public void printCount() { try { for(int i = 5; i > 0; i--) { System.out.println("Counter --- " + i ); } } catch (Exception e) { System.out.println("Thread interrupted."); } } } class ThreadDemo extends Thread { private Thread t; private String threadName; PrintDemo PD; ThreadDemo( String name, PrintDemo pd) { threadName = name; PD = pd; } public void run() { synchronized(PD) { PD.printCount(); } System.out.println("Thread " + threadName + " exiting."); } public void start () { System.out.println("Starting " + threadName ); if (t == null) { t = new Thread (this, threadName); t.start (); } } } public class TestThread { public static void main(String args[]) { PrintDemo PD = new PrintDemo(); ThreadDemo T1 = new ThreadDemo( "Thread - 1 ", PD ); ThreadDemo T2 = new ThreadDemo( "Thread - 2 ", PD ); T1.start(); T2.start(); // wait for threads to end try { T1.join(); T2.join(); } catch ( Exception e) { System.out.println("Interrupted"); } } }
每次執行此程式都會產生相同的結果:
輸出
Starting Thread - 1 Starting Thread - 2 Counter --- 5 Counter --- 4 Counter --- 3 Counter --- 2 Counter --- 1 Thread Thread - 1 exiting. Counter --- 5 Counter --- 4 Counter --- 3 Counter --- 2 Counter --- 1 Thread Thread - 2 exiting.
廣告