NỘI DUNG BÀI VIẾT
Đồ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 đề.
Tham khảo khoá học lập trình Web trong vòng 6 tháng, đảm bảo 100% công việcc đầu ra!
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 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