Cậu gần đúng rồi đó.
Volatile không block thread, mà tất cả các thread sẽ bị buộc đọc và ghi giá trị từ main memory, chứ không phải từ CPU cache (không phải đọc từ biến nha )
Và vì vậy, hẳn nhiên những giải thích về volatile, cũng như phần code demo, đều sai cả
Định nghĩa volatile trích dẫn từ blog:
Là một dạng biến thông báo, nghĩa là nó được dùng để các thread thông báo cho nhau rằng biến có sự thay đổi giá trị, tuy nhiên nó không đảm bảo được là giá trị của biến sẽ được đồng bộ.
Trích dẫn về cơ chế hoạt động của volatile từ blog:
Mặc dù chưa đọc code của trình dịch và jvm, nhưng mình đoán cơ chế hoạt động của volatile sẽ kiểu thế này:
1. Trạng thái ban đầu được set là chưa thay đổi
2. Khi có một luồng gọi đến, nó sẽ kiểm tra xem giá trị có sự thay đổi nào không, nếu không thì block cái luồng gọi lại và chờ đợi cho đến khi có sự thay đổi
3. Khi có 1 luồng thay đổi nó sẽ thông báo đến các luồng đang chờ hãy thức dậy, vừa có sự thay đổi giá trị đó
4. Các luồng đang bị block sẽ thức dậy và thực thi tiếp
“Đoán” (assumption) mà không chứng minh giả thiết là bad practice trong ngành này.
Don’t assume it. Prove it.
Phần “khi nào sử dụng volatile” cũng sai, do việc hiểu sai bản chất kể trên.
Bởi vì volatile không đảm bảo được việc đồng bộ giá trị nên mình cũng chủ yếu dùng để làm thông báo, như ví dụ ở trên, mình dùng để thông báo khi việc chuẩn bị đã hoàn tất và chương trình có thể thực thi.
Tớ recommend cậu nên đọc article khác để biết về định nghĩa, lý do sử dụng, và cách sử dụng volatile. Cậu check ở mục “See also” nhé!
Không chỉ phần volatile, phần Atomic trong blog cũng có những vấn đề riêng của nó.
Trích dẫn định nghĩa Atomic từ blog.
Atomic là một phần trong bộ thư viện java.concurrent
kể từ java 6, nó có khả năng thông báo vừa đảm bảo giá trị sẽ được đồng bộ, vì bên trong nó sử dụng kiểu private volatile int value;
. Nên bạn có thể yên tâm sử dụng để thay thế cho volatile
nếu muốn.
- Atomic không có mục đích sử dụng để thay thế volatile. Nó sử dụng volatile như một phương tiện để đạt mục đích của nó, đảm bảo giá trị nó wrap là atomic.
- Atomic có sử dụng volatile để đảm bảo giá trị được đọc từ main memory, tuy nhiên, lý do class này có thể được sử dụng trong multi thread context một cách hiệu quả, là do sử dụng sun.misc.Unsafe (ở java 8-. Sang Java 9+, sun.misc.Unsafe đã được refactor lại thành jdk.internal.misc.Unsafe). Unsafe class được sử dụng để synchronize, nhưng nhanh hơn so với sử dụng từ khóa synchronized.
Đó là lý do atomic thread-safe.
See also: