Biến volatile trong Java có tác dụng thông báo sự thay đổi giá trị của biến tới các thread khác nhau nếu biến này đang được sử dụng trong nhiều thread.
Để các bạn có thể hiểu rõ hơn, mình đã làm một ví dụ như sau:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
public class VolatileExample { private volatile static int COUNT = 0; public static void main(String[] args) { new ChangeListener().start(); new ChangeMaker().start(); } static class ChangeListener extends Thread { @Override public void run() { int value = COUNT; // Khi giá trị của biến COUNT nhỏ hơn 5, thread này sẽ lặp mãi mãi để kiểm tra giá trị của biến này while (value < 5) { if (value != COUNT) { System.out.println("Count variable changed to : " + COUNT); value = COUNT; } } } } static class ChangeMaker extends Thread { @Override public void run() { int value = COUNT; while (COUNT < 5) { System.out.println("Increasing value of count variable to " + (value + 1)); COUNT = ++value; try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } } } } } |
Trong ví dụ này, mình có hai thread đang sử dụng giá trị của biến COUNT, thread thứ nhất (ChangeMaker) có tác dụng thay đối giá trị của biến COUNT, còn thread thứ hai (ChangeListener) sẽ lắng nghe sự thay đổi đó. Biến COUNT sẽ được khai báo là biến volatile để có thể thông báo được sự thay đổi của nó tới thread ChangeListener.
Kết quả:
1 2 3 4 5 6 7 8 9 10 |
Increasing value of count variable to 1 Count variable changed to : 1 Increasing value of count variable to 2 Count variable changed to : 2 Increasing value of count variable to 3 Count variable changed to : 3 Increasing value of count variable to 4 Count variable changed to : 4 Increasing value of count variable to 5 Count variable changed to : 5 |
Như các bạn thấy, mỗi khi giá trị của biến COUNT thay đổi thì thread ChangeListener sẽ cập nhập sự thay đổi đó liền.
Nếu bây giờ mình bỏ khai báo biến COUNT là biến volatile đi, thì kết quả sẽ như sau:
1 2 3 4 5 6 |
Increasing value of count variable to 1 Count variable changed to : 1 Increasing value of count variable to 2 Increasing value of count variable to 3 Increasing value of count variable to 4 Increasing value of count variable to 5 |
Rõ ràng, thread ChangeListener sẽ không thể cập nhập sự thay đổi giá trị của biến COUNT nữa, và do đó chương trình của chúng ta sẽ chạy mãi mãi.
thuan
Cảm ơn bạn, chỉ có điều giải thích chưa được rõ lắm. Nếu trường hợp mình bỏ static đi và sử dụng thì nó hoạt động bình thường nhé. Ở đây khi mình để static variable mà sử dụng chung cho nhiều Threads. Thì các thread sẽ update giá trị cũ của biến. Do đo volatile là cần thiết cho trường hợp này
Hệ
Mình cám ơn bạn nhé. Bài viết rất hữu ích
Loc
Bài viết sai quá sai. Xóa sleep và tăng điều kiện lên < 5000 và chạy thử vài lần sẽ thấy nó sai ntn.
http://tutorials.jenkov.com/java-concurrency/volatile.html
Khanh Nguyen
Bạn nên chỉ rõ sai chỗ nào nhé!
khuong
Đây là bài demo. bạn hơi gắt :))
Túm lại nên sử dụng AtomicReference cho các tham số cần xử lý.
Kiên
Thanks anh, bài viết hay và hữu ích.
Ngọc Sơn
Chào bạn Khanh Nguyễn, bài viết hay bạn có thể nào làm một bài viết về Design Pattern chẳng hạn như singleton. Mình đọc hoài vẫn chưa hiểu lắm. Thanks bạn nha 😀
Khanh Nguyen
Trong tương lai, chắc chắn mình sẽ có những bài viết về Design Pattern. Bạn theo dõi Hướng Dẫn Java để cập nhập nhé!
Ngọc Sơn
ok thanks ban 😀
Joker
hay lắm bạn ! dễ hiểu !
DatTran
í là cái code nó không chạy ra kết quả ở trên mà chạy ra cái kq ở dưới
Khanh Nguyễn
À, thanks bạn. Chắc lúc copy cái code bỏ vào bài viết mình đã ko còn sử dụng volatile cho biến COUNT nên mới bị sai.
Đã chỉnh sửa rồi nha bạn.
ahii
Hình như có gì đó sai sai thì phải
Khanh Nguyễn
Ý của bạn là gì nhỉ?