TỔNG QUAN
CẤU TRÚC ĐIỀU KHIỂN
VÒNG LẶP
CHUỖI VÀ MẢNG
COLLECTIONS
THƯ VIỆN QUAN TRỌNG
HƯỚNG ĐỐI TƯỢNG
XỬ LÝ LUỒNG
EXCEPTION
LÀM VIỆC VỚI FILE
THAM KHẢO
CÁC CHỦ ĐỀ
BÀI MỚI NHẤT
MỚI CẬP NHẬT

Đồng bộ hóa đa luồng trong Java

Trong bài trước, các bạn đã được học về cách tạo và quản lý luồng trong Java. Sang bài này, tôi sẽ hướng dẫn các bạn tìm hiểu về đồng bộ hóa đa luồng trong Java khi có nhiều luồng cùng thực thi và tôi cũng sẽ đưa ra một số ví dụ minh họa!

1. Đồng bộ luồng trong Java

Để các bạn hiểu về đồng bộ luồng trong Java, tôi đưa ra một ví dụ đơn giản cần sử dụng đến đồng bộ như sau: Giả sử một công ty cấp quyền cho 10 nhân viên có thể thực hiện giao dịch rút tiền và chuyển tiền từ tài khoản ngân hàng chung của công ty và số dư của tài khoản này hiện đang la 10.000$. Vào lúc 9h sáng, giám đốc của công ty này đi giao dịch với khách hàng và quyết định rút 2.000$ từ tài khoản. Trong khi hành động rút tiền của vị giám đốc này đang được thực hiện và vẫn chưa kết thúc thì vào lúc này, người kế toán trưởng của công ty bắt đầu thực hiện kiểm tra số dư tài khoản và tiến hành chuyển tiền cho đối tác của công ty với số tiền là 9.000$.

banquyen png
Bài viết này được đăng tại freetuts.net, không được copy dưới mọi hình thức.

Lúc này, vì giao dịch rút tiền của người giám đốc vẫn chưa kết thúc nên khi người kế toán trưởng kiểm tra số dư thì máy ATM vẫn trả lại số dư là 10.000$ và giao dịch rút 9.000$ của người này vẫn được chấp nhận. Và nếu trong trường hợp này mà không có sự đồng bộ thì cả 2 hành động rút tiền và chuyển tiền đều được thực hiện thành công và vì vậy ngân hàng sẽ mất đi số tiền là 1.000$ → trong trường hợp này bắt buộc cần đến sự đồng bộ hóa giữa các luồng.

Tóm lại, đồng bộ luồng trong Java chính là việc sắp xếp thứ tự các luồng khi truy xuất vào cùng một đối tượng (trong ví dụ trên là số tiền trong tài khoản) sao cho không có sự xung đột dữ liệu. Cơ chế đồng bộ này sẽ khóa hay đồng bộ dữ liệu sử dụng chung để tại một thời điểm chỉ có một luồng được thực thi (rút tiền hoặc chuyển tiền). Chỉ khi nào việc thực thi luồng này kết thúc thì luồng khác mới được thực hiện. Đây chính là cơ chế đồng bộ luồng trong Java.

Để đồng bộ luồng trong Java, chúng ta sẽ sử dụng từ khóa synchronized. Phần dưới đây tôi sẽ trình bày chi tiết.

2. Đồng bộ luồng sử dụng từ khóa synchronized

Để đồng bộ luồng trong Java, chúng ta sẽ sử dụng từ khóa synchronized. Từ khóa này sẽ đứng trước kiểu trả về và đứng sau phạm vi truy cập của phương thức đó.

Để minh họa cách sử dụng từ khóa này, tôi có một ví dụ minh họa bài toán ngân hàng như sau:

Customer.java
package dongboluong;

public class Customer {
	private int taiKhoan = 10000;
	    
	public Customer() {
		System.out.println("Tài khoản hiện có = " + taiKhoan);
	}
	    
	private synchronized void rutTien (int soTienRut) {
		System.out.println("Giao dịch rút tiền đang được thực hiện với" +
				" số tiền = " + soTienRut + "...");
		
		if(taiKhoan < soTienRut) {
			System.out.println("Số tiền trong tài khoản không đủ!");
			try {
				wait();	// phương thức wail sẽ đưa Thread rơi vào trạng thái sleeping
	        } catch (InterruptedException ie) {
	        	System.out.println(ie.toString());
	        }
		}
		
		taiKhoan -= soTienRut;
		System.out.println("Rút tiền thành công. Số tiền hiện có trong tài khoản = " + taiKhoan);
	}
	    
	private synchronized void nopTien(int soTienNop) {
		System.out.println("Giao dịch nộp tiền đang được thực hiện với" +
				" số tiền nộp = " + soTienNop + "...");
		taiKhoan += soTienNop;
		System.out.println("Nộp tiền thành công. Số tiền hiện có trong tài khoản = " + taiKhoan);
		notify();
	}
	    
	public static void main(String[] args) {
		
		final Customer customer = new Customer();
		
		Thread t1 = new Thread(){
			
			public void run() {
				customer.rutTien(20000);
			}
			
		};
		
		t1.start();
	        
		Thread t2 = new Thread(){
            
			public void run() {
				customer.nopTien(30000);
            }
		};
		
		t2.start();
		
	}
	
}

Kết quả sau khi biên dịch chương trình:

ketqua vi du dong bo luong trong java PNG

Giải thích hoạt động của chương trình trên:

Trong ví dụ trên, tôi giả sử số tiền hiện có trong tài khoản ngân hàng là 10.000$. Trong hàm main(), chúng ta có 2 luồng: luồng t1 sẽ thực hiện việc rút tiền và luồng t2 sẽ thực hiện việc nộp tiền vào tài khoản. Trong Thread t1, khách hàng rút tiền với số tiền là 20.000$ thông qua phương thức rutTien(), lúc này số dư trong tài khoản không đủ nên hành động rút tiền này sẽ được đưa vào trạng thái sleeping thông qua dòng lệnh wait(). Sau đó Thread t2 sẽ được thực thi, lúc này khách hàng sẽ nộp vào tài khoản với số tiền là 40.000$ thông qua phương thức nopTien(). Trong phương thức nopTien() này, khi đã nộp tiền thành công thì dòng lệnh notify() sẽ đánh thức Thread đứng trước nó đang ở trạng thái sleeping vì phương thức wait() bị gọi (ở đây là Thread t1). Lúc này phương thức rutTien() sẽ kiểm tra số dư tài khoản là 40.000$ > số tiền cần rút là 20.000$ thì hành động rút tiền này sẽ thành công và số dư tài khoản còn lại là 20.000$.

Lưu ý: Trong khi sử dụng phương thức wait(), các bạn thấy có đoạn try...catch bao bọc bên ngoài, thì trong ví dụ này các bạn đừng để ý đến nó mà chỉ cần hiểu đây là điều bắt buộc khi cần sử dụng wait(). Chi tiết về try...catch tôi sẽ trình bày trong chương sau.

3. Lời kết

Trong bài này, tôi đã hướng dẫn các bạn tìm hiểu về cách đồng bộ luồng trong Java bằng cách sử dụng từ khóa synchronized. Sang bài sau, tôi sẽ trình bày các phần còn lại liên quan đến Thread. Các bạn theo dõi nhé!

Cùng chuyên mục:

Khi nào dùng Default Methods trong Java 8

Khi nào dùng Default Methods trong Java 8

Ở 2 bài trước chúng ta đã tìm hiểu 2 tính năng mới của Java…

Cách chuyển chữ hoa thành chữ thường trong Java

Cách chuyển chữ hoa thành chữ thường trong Java

Trong bài viết này chúng ta sẽ tìm hiểu về cách chuyển đổi chữ in…

Bài tập tính tổng các số tự nhiên trong Java

Bài tập tính tổng các số tự nhiên trong Java

Các số dương 1, 2, 3, 4, ... được gọi là các số tự nhiên,…

Cách chuyển chữ thường thành chữ hoa trong Java

Cách chuyển chữ thường thành chữ hoa trong Java

Trong chuỗi có thể vừa có ký tự thường vừa có ký tự hoa, nhưng…

Cách viết hoa ký tự đầu tiên trong Java

Cách viết hoa ký tự đầu tiên trong Java

Để hiểu được bài này, các bạn cần có kiến thức căn bản về Java…

Hướng dẫn chuyển đổi giờ phút giây trong Java

Hướng dẫn chuyển đổi giờ phút giây trong Java

Để hiểu được chương trình, các bạn cần có kiến thức cơ bản về Java.…

Cách lấy thời gian hiện tại trong Java

Cách lấy thời gian hiện tại trong Java

Để hiểu được bài viết này, các bạn cần có kiến thức cơ bản sau…

Cách làm tròn số trong Java

Cách làm tròn số trong Java

Khi thực hiện tính toán, việc kết quả ra một con số thập phân dài…

Cách tìm ma trận chuyển vị trong Java

Cách tìm ma trận chuyển vị trong Java

Quá trình hoán đổi giữa hàng và cột được gọi là chuyển vị của ma…

Cách chuyển ArrayList thành mảng và ngược lại trong Java

Cách chuyển ArrayList thành mảng và ngược lại trong Java

Để hiểu được bài này, các bạn cần có kiến thức cơ bản về mảng…

Cách nối hai mảng trong Java

Cách nối hai mảng trong Java

Mình sẽ thực hiện hai chương trình nối mảng. Chương trình thứ nhất nối hai…

Cách xóa khoảng trắng của chuỗi trong Java

Cách xóa khoảng trắng của chuỗi trong Java

Mình sẽ thực hiện hai chương trình khác nhau để các bạn có thể hiểu…

In ra tam giác bằng ký tự * và số trong Java

In ra tam giác bằng ký tự * và số trong Java

Mình sẽ giới thiệu cách để in ra các tam giác bằng ký tự *…

Tìm số lớn nhất trong mảng Java

Tìm số lớn nhất trong mảng Java

Các bạn cần tìm hiểu về mảng, cách khởi tạo và in mảng trong Java…

Tìm ước của một số nguyên trong Java

Tìm ước của một số nguyên trong Java

Trong bài viết này chúng ta sẽ tìm hiểu cách tìm tất cả các ước…

Cách kiểm tra số hoàn hảo trong Java

Cách kiểm tra số hoàn hảo trong Java

Cách kiểm tra số đối xứng trong Java

Cách kiểm tra số đối xứng trong Java

Trong bài viết này chúng ta sẽ kiểm tra một số có phải là số…

Đảo ngược một số trong Java

Đảo ngược một số trong Java

Mình sẽ giới thiệu các bạn cách đảo ngược một số sử dụng vòng lặp…

Tìm bội chung nhỏ nhất trong Java

Tìm bội chung nhỏ nhất trong Java

Mình sẽ sử dụng hai cách khác nhau để tìm BCNN. Cách thứ nhất mình…

Cách hoán đổi hai số trong Java

Cách hoán đổi hai số trong Java

Trong phần này mình sẽ sử dụng một biến tạm temp() làm biến trung gian…

Top