Bài 32: Thread synchronization trong Java - Lập trình Java cơ bản

Đăng bởi: Admin | Lượt xem: 3183 | Chuyên mục: Java


1. Giới thiệu

Khi chúng ta bắt đầu hai hoặc nhiều thread bên trong một chương trình, có thể có tình huống khi nhiều thread cố gắng truy cập cùng một nguồn và cuỗi cùng chúng có thể đưa ra kết quả không như dự kiến do sự xảy ra đồng thời. Ví dụ, nếu nhiều thread cố gắng ghi vào trong cùng một file, thì khi đó chúng có thể làm ngắt dữ liệu, bởi vì một trong các thread có thể override dữ liệu hoặc trong khi một thread mở file cùng thời điểm với thread khác đang đóng file này.
Vì thế, nó là cần thiết để đồng bộ hoạt đồng của nhiều thread và đảm bảo rằng chỉ có một thread có thể truy cập nguồn tại một thời điểm. Điều này được triển khai bởi sử dụng một khái niệm được gọi là monitors. Mỗi đối tượng trong Java được xem như là một monitor, mà một thread có thể lock hoặc unlock. Chỉ có một thread tại một thời điểm có thể giữ một lock trên một monitor.
Ngôn ngữ lập trình Java cung cấp một cách rất thuận tiện để tạo các thread và đồng bộ hóa tác vụ của chúng bởi sử dụng các khối synchronized. Bạn giữ nguồn chia sẻ (shared resource) bên trong block này. Sau đây là form chung của lệnh synchronized trong Java.
synchronized(objectidentifier) {
   // Access shared variables and other shared resources
}
Tại đây, objectidentifier là một tham chiếu tới một đối tượng, mà có lock liên kết với monitor, mà lệnh synchronized biểu diễn. Bây giờ, chúng ta sẽ xem xét 2 ví dụ, mà sẽ in một bộ đếm (counter) bởi sử dụng 2 thread khác nhau. Khi các thread chưa được synchronized, chúng in giá trị counter mà không liên tục, nhưng khi chúng ta in counter bởi việc đặt bên trong khối synchronized(), thì nó in counter theo dãy liên tục cho cả hai thread.

2. Ví dụ về đa luồng mà không sử dụng Synchronization trong Java

Ví dụ đơn giản sau có thể hoặc không thể in giá trị counter liên tục và mỗi lần chúng ta chạy nó, nó cho kết quả khác nhau dựa vào tính khả dụng của CPU tới một thread.
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");
      }
   }
}
Kết quả thu được:
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.

2. Ví dụ về đa luồng sử dụng Synchronization trong Java

Trong ví dụ sau, chúng tôi sử dụng lệnh synchronized trong Java, mà sẽ in giá trị counter liên tục và cho cùng kết quả mỗi lần chúng ta chạy chương trình.  
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");
      }
   }
}
Kết quả thu được:
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.
Bài tiếp theo: Tổng quan về Java AWT >>
vncoder logo

Theo dõi VnCoder trên Facebook, để cập nhật những bài viết, tin tức và khoá học mới nhất!