"Chào, Amigo!"

"Chào, Ellie!"

"Tôi muốn nói với bạn về công cụ sửa đổi dễ bay hơi. Bạn có biết đó là gì không?"

"Cái gì đó liên quan đến sợi chỉ. Tôi không nhớ chính xác."

"Vậy thì hãy lắng nghe. Dưới đây là một số chi tiết kỹ thuật dành cho bạn:"

"Một máy tính có hai loại bộ nhớ: bộ nhớ chung (thông thường) và bộ nhớ tích hợp trong bộ xử lý. Bộ nhớ tích hợp trong bộ xử lý được chia thành các thanh ghi, bộ đệm cấp một (L1), bộ đệm cấp hai (L2) và cấp ba (L3)."

"Các loại bộ nhớ này có tốc độ khác nhau. Bộ nhớ nhanh nhất và nhỏ nhất là thanh ghi, sau đó là bộ đệm của bộ xử lý (L1, L2, L3) và cuối cùng là bộ nhớ chung (chậm nhất)."

"Bộ nhớ chung và bộ đệm của bộ xử lý hoạt động ở các tốc độ cực kỳ khác nhau, do đó, máy Java cho phép mỗi luồng lưu trữ các biến được sử dụng thường xuyên nhất trong bộ nhớ luồng cục bộ (trong bộ đệm của bộ xử lý)."

"Quá trình này bằng cách nào đó có thể được kiểm soát?"

"Không hẳn. Tất cả công việc được thực hiện bởi máy Java. Nó rất thông minh khi tối ưu hóa hiệu suất."

"Nhưng đây là lý do tại sao tôi nói với bạn điều này. Có một vấn đề nhỏ. Khi hai luồng đang làm việc với cùng một biến, mỗi luồng có thể lưu một bản sao trong bộ đệm cục bộ của chính nó. Và sau đó một luồng có thể thay đổi biến, nhưng luồng thứ hai có thể không thấy sự thay đổi, bởi vì nó vẫn đang hoạt động với bản sao biến của chính nó."

"Chà, vậy thì có thể làm gì?"

"Những người tạo ra Java đã cung cấp một từ khóa đặc biệt cho tình huống này: dễ bay hơi. Nếu một biến được truy cập từ các luồng khác nhau, bạn cần đánh dấu nó bằng công cụ sửa đổi dễ bay hơi, vì vậy máy Java sẽ không đưa nó vào bộ đệm. Đây là cách nó thường nhìn:"

public volatile int count = 0;

"Ồ, tôi nhớ rồi. Bạn đã đề cập đến điều này. Tôi đã biết điều này."

"Chắc chắn rồi. Nhưng anh chỉ nhớ nó khi tôi nói với anh."

"Ân, ta có chút quên mất."

"Sự lặp lại là mẹ của việc học!"

"Dưới đây là một số thông tin mới về công cụ sửa đổi dễ bay hơi. Công cụ sửa đổi dễ bay hơi chỉ đảm bảo rằng biến sẽ được đọc và ghi một cách an toàn. Nó không đảm bảo rằng nó sẽ được thay đổi một cách an toàn."

"Có gì khác biệt?"

"Hãy xem cách một biến được thay đổi:"

Mã số Điều gì thực sự xảy ra: Sự miêu tả
count++
register = count;

register = register+1;

count = register;
Bước 1.
Giá trị của biến đếm được sao chép từ bộ nhớ chung vào thanh ghi bộ xử lý.

Bước 2.
Bên trong bộ xử lý, biến thanh ghi được tăng thêm 1.

Bước 3.
Giá trị của biến được sao chép từ bộ xử lý sang bộ nhớ chung.

"Chà! Vì vậy, tất cả các biến chỉ được thay đổi trong bộ xử lý?"

"Chuẩn rồi."

"Và các giá trị được sao chép qua lại: từ bộ nhớ đến bộ xử lý và ngược lại?"

"Chuẩn rồi."

"Công cụ sửa đổi dễ bay hơi đảm bảo rằng khi số lượng biến được truy cập, nó sẽ được đọc từ bộ nhớ (bước 1). Và nếu một chuỗi muốn gán một giá trị mới, nó chắc chắn sẽ nằm trong bộ nhớ chung (bước 3)."

"Nhưng máy Java không đảm bảo rằng sẽ không có bất kỳ luồng nào chuyển đổi giữa bước 1 và bước 3."

"Vì vậy, tăng biến lên 1 thực sự là ba thao tác?"

"Đúng."

"Và nếu hai luồng đồng thời muốn thực thi đếm ++, thì chúng có thể can thiệp lẫn nhau không?"

"Ừ, xem đi:"

chủ đề 1 chủ đề 2 Kết quả
register1 = count;
register1++;
count = register1;
register2 = count;
register2++;
count = register2;
register1 = count;
register2 = count;
register2++;
count = register2;
register1++;
count = register1;

"Vì vậy, bạn có thể truy cập vào biến, nhưng việc thay đổi nó vẫn có rủi ro?"

"Chà, bạn có thể thay đổi nó, chỉ cần cẩn thận ☺"

"Làm sao?"

" đồng bộ hóa  là người bạn tốt nhất của chúng tôi."

"Tôi hiểu rồi."