กำลังเข้าถึงBool field atomic ใน C # หรือไม่ โดยเฉพาะอย่างยิ่งฉันต้องใส่กุญแจล็อค:
class Foo
{
private bool _bar;
//... in some function on any thread (or many threads)
_bar = true;
//... same for a read
if (_bar) { ... }
}
กำลังเข้าถึงBool field atomic ใน C # หรือไม่ โดยเฉพาะอย่างยิ่งฉันต้องใส่กุญแจล็อค:
class Foo
{
private bool _bar;
//... in some function on any thread (or many threads)
_bar = true;
//... same for a read
if (_bar) { ... }
}
คำตอบ:
ใช่.
การอ่านและเขียนประเภทข้อมูลต่อไปนี้ ได้แก่ ประเภท atomic: bool, char, byte, sbyte, short, ushort, uint, int, float และประเภทอ้างอิง
ที่พบในC # ภาษา Spec
แก้ไข: ควรทำความเข้าใจกับคำหลักที่มีความผันผวนด้วยเช่นกัน
Interlocked.Add(ref myInt);
เช่น?
i++
เท่ากับi=i+1
หมายความว่าคุณอ่านอะตอมแล้วบวกแล้วเขียนอะตอม เธรดอื่นสามารถแก้ไขได้i
หลังจากอ่าน แต่ก่อนเขียน ตัวอย่างเช่นสองเธรดที่ทำi++
พร้อมกันบนเดียวกันฉันสามารถอ่านพร้อมกันได้ (และอ่านค่าเดียวกัน) เพิ่มหนึ่งเธรดจากนั้นทั้งสองเขียนค่าเดียวกันเพิ่มเพียงครั้งเดียว Interlocked.Add ป้องกันสิ่งนี้ ตามกฎทั่วไปความจริงที่ว่าประเภทคืออะตอมจะมีประโยชน์ก็ต่อเมื่อมีการเขียนเธรดเพียงชุดเดียว แต่มีการอ่านหลายเธรด
ตามที่ระบุไว้ข้างต้นบูลเป็นปรมาณู แต่คุณยังต้องจำไว้ว่ามันขึ้นอยู่กับสิ่งที่คุณต้องการทำด้วย
if(b == false)
{
//do something
}
ไม่ใช่การทำงานของอะตอมซึ่งหมายความว่าค่า b สามารถเปลี่ยนแปลงได้ก่อนที่เธรดปัจจุบันจะรันโค้ดหลังจากคำสั่ง if
การเข้าถึงบูลเป็นปรมาณู แต่นั่นไม่ใช่เรื่องราวทั้งหมด
คุณไม่ต้องกังวลเกี่ยวกับการอ่านค่าที่ 'เขียนไม่สมบูรณ์' - ยังไม่ชัดเจนว่าสิ่งที่อาจหมายถึงบูลในกรณีใด ๆ - แต่คุณต้องกังวลเกี่ยวกับแคชของโปรเซสเซอร์อย่างน้อยถ้ารายละเอียดของ เวลาเป็นปัญหา หากเธรด # 1 ทำงานบนคอร์ A มี_bar
แคชของคุณและ_bar
ได้รับการอัปเดตโดยเธรด # 2 ที่ทำงานบนคอร์อื่นเธรด # 1 จะไม่เห็นการเปลี่ยนแปลงทันทีเว้นแต่คุณจะเพิ่มการล็อกประกาศ_bar
เป็นvolatile
หรือแทรกการโทรอย่างชัดเจนThread.MemoryBarrier()
เพื่อทำให้ไม่ถูกต้อง ค่าแคช
var fatObject = new FatObject(); Thread.MemoryBarrier(); _sharedRefToFat = fatObject;
แนวทางที่ฉันใช้และฉันคิดว่าถูกต้องคือ
volatile bool b = false;
.. rarely signal an update with a large state change...
lock b_lock
{
b = true;
//other;
}
... another thread ...
if(b)
{
lock b_lock
{
if(b)
{
//other stuff
b = false;
}
}
}
โดยพื้นฐานแล้วเป้าหมายคือเพื่อหลีกเลี่ยงการล็อกวัตถุซ้ำ ๆ ในการทำซ้ำทุกครั้งเพียงเพื่อตรวจสอบว่าเราจำเป็นต้องล็อกเพื่อให้ข้อมูลการเปลี่ยนแปลงสถานะจำนวนมากซึ่งเกิดขึ้นน้อย ฉันคิดว่าวิธีนี้ใช้ได้ผล และถ้าต้องการความสม่ำเสมอที่แน่นอนฉันคิดว่าการระเหยน่าจะเหมาะสมกับ b bool
lock()
, volatile
คุณไม่จำเป็นต้อง