Đồng bộ (Synchronization)

Threading

Đồng bộ trong java (Synchronization in java) là khả năng kiểm soát truy cập của nhiều luồng đến bất kỳ nguồn tài nguyên dùng chung (shared resource) nào.

Vấn đề của đa luồng là thường xuyên có trường hợp nhiều luồng muốn truy cập cùng một nguồn tài nguyên vào cùng một thời điểm. Ví dụ một luồng muốn cập nhật, trong khi luồng khác cố gắng xóa bỏ dữ liệu dẫn dến dữ liệu bị sai lệch. Trong trường hợp này, đồng bộ hóa là giải pháp cần thiết.

Đồng bộ hóa là hành động giới hạn số luồng được phép truy cập tới một nguồn tài nguyên xuống còn 1 luồng tại bất kỳ thời điểm nào. Nhờ đó, nghiệp vụ của chương trình vẫn được nhất quán, trong khi vẫn tận dụng được ưu điểm về hiệu năng tới từ đa luồng.

Cách tốt nhất để xem xét lợi ích của đồng bộ là xem xét một số ví dụ mà tại đó, bất đồng bộ gây ra vấn đề.

Vấn đề xảy ra khi không sử dụng đồng bộ 

Trong ví dụ này, không có sự đồng bộ, vì vậy đầu ra không phù hợp. Hãy xem ví dụ:

class Table {
    void printTable(int n) {// method không synchronized
        for (int i = 1; i <= 5; i++) {
            System.out.println(n * i);
            try {
                Thread.sleep(400);
            } catch (Exception e) {
                System.out.println(e);
            }
        }
    }
}

class MyThread1 extends Thread {
    Table t;
 
    MyThread1(Table t) {
        this.t = t;
    }
 
    public void run() {
        t.printTable(5);
    }
}

class MyThread2 extends Thread {
    Table t;
 
    MyThread2(Table t) {
        this.t = t;
    }
 
    public void run() {
        t.printTable(100);
    }
}
public class TestSynchronization1 {
    public static void main(String args[]) {
        Table obj = new Table();// tao mot object
        MyThread1 t1 = new MyThread1(obj);

        MyThread2 t2 = new MyThread2(obj);
        t1.start();
        t2.start();
    }
}
Output: 
5
100
200
10
300
15
400
20
25
500

Phương thức đồng bộ (synchronized method) 

Nếu bạn khai báo bất kỳ phương pháp nào với từ khóa synchronized, nó được gọi là phương thức đồng bộ. 

Phương thúc đồng bộ được sử dụng để khóa một đối tượng cho bất kỳ tài nguyên được chia sẻ. 

Khi một luồng gọi một phương thức đồng bộ, nó sẽ tự động khóa cho đối tượng đó và giải phóng nó khi luồng hoàn thành nhiệm vụ.

Ví dụ về phương thức đồng bộ (synchronized method) 


class Table {
    synchronized void printTable(int n) { // synchronized method
        for (int i = 1; i <= 5; i++) {
            System.out.println(n * i);
            try {
                Thread.sleep(400);
            } catch (Exception e) {
                System.out.println(e);
            }
        }
    }
}

 
class MyThread1 extends Thread {
    Table t;

    MyThread1(Table t) {
        this.t = t;
    }
 
    public void run() {
        t.printTable(5);
    }
}

 
class MyThread2 extends Thread {
    Table t;

    MyThread2(Table t) {
        this.t = t;
    }
 
    public void run() {
        t.printTable(100);
    }
}

 
public class TestSynchronization2 {

    public static void main(String args[]) {
        Table obj = new Table();// tao mot object

        MyThread1 t1 = new MyThread1(obj);
        MyThread2 t2 = new MyThread2(obj);

        t1.start();
        t2.start();

    }
}


Output: 
5
10
15
20
25
100
200
300
400
500

Ví dụ về synchronized method sử dụng lớp nặc danh 

Trong chương trình sau đây, chúng ta đã tạo ra hai thread bằng lớp ẩn danh, do đó phải viết ít code hơn. 


class Table {
    synchronized void printTable(int n) {// synchronized method
        for (int i = 1; i <= 5; i++) {
            System.out.println(n * i);
            try {
                Thread.sleep(400);
            } catch (Exception e) {
                System.out.println(e);
            }
        }
    }
}

 
public class TestSynchronization3 {

    public static void main(String args[]) {
        final Table obj = new Table();// tao mot object
 
        Thread t1 = new Thread() {
            public void run() {
                obj.printTable(5);
            }
        };

        Thread t2 = new Thread() {
            public void run() {
                obj.printTable(100);
            }
        };
 
        t1.start();
        t2.start();

    }
}


Output: 
5
10
15
20
25
100
200
300
400
500

Khối đồng bộ trong java

Khối đồng bộ trong java (Synchronized block) có thể được sử dụng để thực hiện đồng bộ hóa trên bất kỳ tài nguyên cụ thể nào của phương thức. 

Giả sử có 50 dòng code trong phương thức, nhưng bạn chỉ muốn đồng bộ hóa 5 dòng, bạn có thể sử dụng khối đồng bộ. 

Nếu bạn đặt tất cả các dòng code của phương thức trong khối đồng bộ, nó sẽ hoạt động giống như phương thức đồng bộ. 

Các điểm cần nhớ về khối đồng bộ

  • Khối đồng bộ được sử dụng để khóa một đối tượng cho bất kỳ tài nguyên dùng chung nào.
  • Phạm vi của khối đồng bộ nhỏ hơn phương thức.

Khai báo để sử dụng khối đồng bộ:

synchronized (object reference expression) {   
    //code block   
}  

Ví dụ về khối đồng bộ 

Dưới đây là ví dụ đơn giản về khối đồng bộ trong java. 

File: TestSynchronizedBlock1.java 

class Table {
    void printTable(int n) {
        synchronized (this) {// Khoi dong bo (synchronized block)
            for (int i = 1; i <= 5; i++) {
                System.out.println(n * i);
                try {
                    Thread.sleep(400);
                } catch (Exception e) {
                    System.out.println(e);
                }
            }
        }
    }// Ket thuc phuong thuc
}

 
class MyThread1 extends Thread {
    Table t;

    MyThread1(Table t) {
        this.t = t;
    }

    public void run() {
        t.printTable(5);
    }
}


class MyThread2 extends Thread {
    Table t;

    MyThread2(Table t) {
        this.t = t;
    }

    public void run() {
        t.printTable(100);
    }
}


public class TestSynchronizedBlock1 {
    public static void main(String args[]) {

        Table obj = new Table();// tao object duy nhat
        MyThread1 t1 = new MyThread1(obj);

        MyThread2 t2 = new MyThread2(obj);
        t1.start();

        t2.start();
    }

}


Output: 
5
10
15
20
25
100
200
300
400
500

Ví dụ tương tự về khối đồng bộ bởi việc sử dụng lớp nặc danh 

Dưới đây là ví dụ đơn giản về khối đồng 


class Table {
    void printTable(int n) {
        synchronized (this) { // khoi dong bo (synchronized block)
            for (int i = 1; i <= 5; i++) {
                System.out.println(n * i);
                try {
                    Thread.sleep(400);
                } catch (Exception e) {
                    System.out.println(e);
                }
            }
        }
    } // Ket thuc phuong thuc
}

 
public class TestSynchronizedBlock2 {
    public static void main(String args[]) {
        final Table obj = new Table();// tao object duy nhat
 
        Thread t1 = new Thread() {
            public void run() {
                obj.printTable(5);
            }
        };

        Thread t2 = new Thread() {
            public void run() {
                obj.printTable(100);
            }
        };
 
        t1.start();
        t2.start();
    }
}


Output: 
5
10
15
20
25
100
200
300
400
500

Hãy tham gia nhóm Học lập trình để thảo luận thêm về các vấn đề cùng quan tâm.

Leave a Reply

Your email address will not be published. Required fields are marked *