Java 教程

Java 控制語句

面向物件程式設計

Java 內建類

Java 檔案處理

Java 錯誤和異常

Java 多執行緒

Java 同步

Java 網路程式設計

Java 集合

Java 介面

Java 資料結構

Java 集合演算法

高階 Java

Java 雜項

Java APIs 和框架

Java 類引用

Java 有用資源

Java - 執行緒同步



執行緒同步的必要性?

當我們在程式中啟動兩個或多個執行緒時,可能會出現多個執行緒嘗試訪問同一資源的情況,最終由於併發問題而產生不可預見的結果。例如,如果多個執行緒嘗試寫入同一個檔案,則它們可能會損壞資料,因為其中一個執行緒可能會覆蓋資料,或者當一個執行緒正在開啟同一個檔案時,另一個執行緒可能正在關閉同一個檔案。

因此,需要同步多個執行緒的操作,並確保在給定時間點只有一個執行緒可以訪問該資源。這是使用稱為監視器的概念實現的。Java 中的每個物件都與一個監視器關聯,執行緒可以鎖定或解鎖該監視器。同一時間只有一個執行緒可以持有監視器的鎖。

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.
java_multithreading.htm
廣告