Khi nào tôi nên sử dụng biến động/Thread.MemoryBarrier() cho an toàn luồng?Khi nào sử dụng 'bay hơi' hoặc 'Thread.MemoryBarrier()' trong mã khóa an toàn? (C#)
Trả lời
Bạn sử dụng volatile
/Thread.MemoryBarrier()
khi bạn muốn truy cập một biến trên các chuỗi mà không cần khóa. Ví dụ:
Biến là nguyên tử, chẳng hạn như int
, luôn đọc và viết toàn bộ cùng một lúc. Điều đó có nghĩa là bạn sẽ không bao giờ nhận được một nửa giá trị trước khi một chủ đề khác thay đổi nó và một nửa khác sau khi nó đã thay đổi. Vì lý do đó bạn có thể đọc và ghi giá trị một cách an toàn trong các chủ đề khác nhau mà không cần đồng bộ hóa.
Tuy nhiên, trình biên dịch có thể tối ưu hóa một số lần đọc và ghi, mà bạn ngăn chặn bằng từ khóa volatile
.Nếu bạn ví dụ có một vòng lặp như thế này:
sum = 0;
foreach (int value in list) {
sum += value;
}
Trình biên dịch thực sự có thể làm các phép tính trong một thanh ghi bộ xử lý và chỉ viết những giá trị cho sum
biến sau vòng lặp. Nếu bạn thực hiện biến số sum
volatile
, trình biên dịch sẽ tạo mã đọc và ghi biến cho mọi thay đổi, để giá trị của nó được cập nhật trong suốt vòng lặp.
Có gì sai với
private static readonly object syncObj = new object();
private static int counter;
public static int NextValue()
{
lock (syncObj)
{
return counter++;
}
}
?
Điều này thực hiện tất cả các khóa, rào cản bộ nhớ, v.v. cần thiết cho bạn. Nó được hiểu rõ và dễ đọc hơn bất kỳ mã đồng bộ hóa tùy chỉnh nào dựa trên volatile
và Thread.MemoryBarrier()
.
EDIT
Tôi không thể nghĩ ra một kịch bản trong đó tôi muốn sử dụng volatile
hay Thread.MemoryBarrier()
. Ví dụ
private static volatile int counter;
public static int NextValue()
{
return counter++;
}
là không tương đương với đoạn code trên và là không thread-safe (volatile
không làm ++
kỳ diệu trở thành thread-safe).
Trong một trường hợp như thế này:
private static volatile bool done;
void Thread1()
{
while (!done)
{
// do work
}
}
void Thread2()
{
// do work
done = true;
}
(mà nên làm việc) Tôi muốn sử dụng một ManualResetEvent để báo hiệu khi thread2 được thực hiện.
Không có gì 'sai' với mã của bạn. Tôi đang cố gắng nắm bắt các tình huống trong đó dễ bay hơi và MemoryBarrier áp dụng. Như trong câu trả lời của Jon Skeet ở đây: http://stackoverflow.com/questions/395232/we-need-to-lock-a-net-int32-when-reading-it-in-a-multithreaded-code. – Alex
.net cũng có một mô hình bộ nhớ khá nghiêm ngặt, chẳng hạn như đọc hoặc viết không thể thực hiện theo cách viết khác. –
Mặc dù thông số ECMA có mô hình bộ nhớ khá yếu, vì vậy bạn có thể muốn xem nó, hãy xem http://www.bluebytesoftware.com/blog/2007/11/10/CLR20MemoryModel.aspx và http: // blog .msdn.com/cbrumme/archive/2003/05/17/51445.aspx –
Về cơ bản nếu bạn đang sử dụng bất kỳ loại đồng bộ hóa nào khác để làm cho luồng của bạn an toàn thì bạn không cần.
Hầu hết các cơ chế khóa (bao gồm khóa) tự động ngụ ý một hàng rào bộ nhớ để nhiều bộ xử lý có thể nhận được thông tin chính xác.
Dễ bay hơi và bộ nhớBarrier chủ yếu được sử dụng trong các trường hợp không có khóa, nơi bạn đang cố tránh hình phạt khóa hiệu suất.
Chỉnh sửa: Bạn nên đọc this article bởi Joe Duffy về mô hình bộ nhớ CLR 2.0, nó làm rõ rất nhiều thứ (nếu bạn thực sự quan tâm, bạn nên đọc TẤT CẢ bài viết từ Joe Duffie, người lớn nhất chuyên gia song song trong .NET)
+1, nhưng điều đó hoàn toàn rõ ràng. Nếu bạn làm những gì dtb làm, dễ bay hơi/Thread.MemoryBarrier là không cần thiết. Cũng có những tình huống dễ bay hơi trên một thành viên không đủ. – Skurmedel
Như tên ngụ ý bảo đảm dễ bay hơi, giá trị bộ đệm được chuyển sang bộ nhớ sao cho tất cả các chuỗi đều thấy cùng giá trị. Ví dụ, nếu tôi có một số nguyên có ghi mới nhất được lưu trong bộ nhớ cache, các chủ đề khác có thể không thấy điều đó. Họ thậm chí có thể xem bản sao bộ nhớ cache của số nguyên đó. Đánh dấu một biến là dễ bay hơi làm cho nó được đọc trực tiếp từ bộ nhớ.
Sriwantha Sri Aravinda Attanayake
- 1. dễ bay hơi và Thread.MemoryBarrier trong C#
- 2. Khi nào thì từ khóa dễ bay hơi được sử dụng trong C#?
- 3. dễ bay hơi DateTime
- 4. Sử dụng đúng sig_atomic_t dễ bay hơi
- 5. Thực tiễn tốt nhất để sử dụng từ khóa 'dễ bay hơi' trong VS2012
- 6. Khóa thực tế có quan trọng khi quyết định sử dụng dễ bay hơi không?
- 7. Trong khi (! Dễ bay hơi); làm gì?
- 8. Đây có phải là (bool dễ bay hơi) luôn luôn là chủ đề an toàn không?
- 9. Khi nào sử dụng dễ bay hơi với Bộ nhớ CUDA chia sẻ
- 10. dễ bay hơi weirdness
- 11. dễ bay hơi tương đương trong VB.NET
- 12. Dễ bay hơi khi được đồng bộ hóa với nhau
- 13. Dễ bay hơi hoặc đồng bộ cho loại nguyên thủy?
- 14. Là một int dễ bay hơi trong Java thread-safe?
- 15. Java câu hỏi biến dễ bay hơi
- 16. Ví dụ hoàn chỉnh để sử dụng từ khóa dễ bay hơi trong java?
- 17. Mã không an toàn trong C#
- 18. Nếu bạn sử dụng HTTPS, thông số URL của bạn sẽ an toàn khi đánh hơi?
- 19. Biến dễ bay hơi
- 20. ngữ nghĩa dễ bay hơi trong C99
- 21. dễ bay hơi và có thể thay đổi trong C++
- 22. Mã an toàn và không an toàn
- 23. Khi nào nên sử dụng dây khóa trong C#?
- 24. Mảng an toàn không có khóa an toàn
- 25. quá tải dễ bay hơi?
- 26. Khai báo một đối tượng dễ bay hơi
- 27. Sử dụng dễ bay hơi để liên lạc một chiều giữa các chủ đề trong .NET
- 28. Ví dụ mã C thể hiện dễ bay hơi trong việc tháo gỡ?
- 29. Ngữ nghĩa cấu trúc dễ bay hơi
- 30. const biến động, đăng ký biến động, tĩnh dễ bay hơi trong C++
+1, nhưng trong trường hợp nào thì vấn đề là trình biên dịch sẽ tạo mã đọc và ghi biến cho mọi thay đổi? – dtb
Đó là chủ yếu là mong muốn khi luồng dtb, nếu không một sợi có thể có được một giá trị khác hơn so với khác và tất cả các loại điều điên rồ có thể xảy ra. – Skurmedel
Vâng, đó hoặc sử dụng một rào cản bộ nhớ. – Skurmedel