Hỏi về Synchronized trong Java

Theo em hiểu thì từ khóa synchronized là để trong cùng 1 thời điểm, chỉ có 1 thread được tác động tới dữ liệu được synchronized.

Vậy tại sao demo lại như này ạ

public class CustomerBankAccount {
    private int balance = 0;

    public synchronized  void deposit(amount) { // gửi tiền
        ballance += amount;
    }

    public synchronized void withdraw(amount) { // rút tiền hoặc chuyển khoản
        if (ballance > amount)
            ballance -= amount;
    }

    public synchronized int getBalance() {
        return ballance;
    }
}

nếu đúng như định nghĩa thì cái cần được synchronized phải là balance chứ ạ? Chứ có phải là 2 method nạp tiền và rút tiền đâu (Vì ở demo người ta cho 1 thread chạy rút tiền, 1 thread chạy nạp tiền nên em nghĩ là có bao giờ cùng 1 lúc chạy cùng rút tiền hoặc cùng nạp tiền đâu?) nên cái synchronized theo định nghĩa phải là balance chứ nhỉ?

Em cám ơn

1 Like

Thử nghĩ nếu không có từ khóa synchronizeddeposit()withdraw() thì chuyện gì xảy ra nếu có nhiều luồng cùng thực thi một phương thức?

Giả sử có 2 luồng cùng gọi withdraw() cùng 1 lúc (thực sự là không cùng 1 thời điểm, nhưng sai số rất nhỏ). Cả 2 đều chạy qua điều kiện if và cùng bắt đầu rút tiền. Số dư còn lại sẽ thế nào?
Sẽ là số dư của của luồng nào kết thúc sau! Vâng rút tiền và sinh lời đây rồi.

Ác mộng với gửi tiền tương tự và “sinh lỗ”.
Gửi đồng loạt, nhưng chỉ nhận được số tiền của “thằng” kết thúc cuối cùng.

Bởi thế mà chỉ 1 luồng được thực hiện thay đổi dữ liệu, các luồng sau phải chờ để đảm bảo dữ liệu chuẩn xác.

À mà, câu hỏi của bạn đáng lẽ nên ngược lại!
Tại sao getBalance() cũng cần từ khóa synchronized chứ? Trong phương thức này chỉ trả về mà không thay đổi dữ liệu.

4 Likes

Không thể synchornized các biến kiểu primitve. int là một kiểu dữ liệu primitive, vì vậy không thể “synchronized(this.balance)”.

Java chỉ có thể synchronized một object, và các kiểu dữ liệu primitve thì nó đặc biệt hơn nên không synchronized được, phải synchronized cái object kiểu CustomerBankAccount đó.

Cái method “get” kia không làm thay đổi ballance thì không nên dùng synchronized vì synchronized method sẽ khoá cả object lại.

Cá nhân mình thường không dùng synchronized method mà thường dùng một object khác để lock, như vậy object đó vẫn có thể tương tác được trong khi method đó đang được xử lý.

2 Likes

Trường hợp nhiều tài khoản chuyển vào một lúc không phải là không có.

3 Likes

Cái method đó nó chỉ có update cái balance thì nó synchronized luôn chứ sao, đặt trường hợp là cái hàm đó làm nhiều việc mà em chỉ muốn synchronized cái balance thì em làm thế nào?

The synchronized keyword can be used to mark four different types of blocks:

Instance methods
Static methods
Code blocks inside instance methods
Code blocks inside static methods
3 Likes
83% thành viên diễn đàn không hỏi bài tập, còn bạn thì sao?