ในกรณีที่การอ่านมีจำนวนมากกว่าการเขียนอย่างมากหรือ (อย่างไรก็ตามบ่อยครั้ง) การเขียนไม่พร้อมกันวิธีการคัดลอกเมื่อเขียนอาจเหมาะสม
การใช้งานที่แสดงด้านล่างคือ
- lockless
- เร็วอย่างเห็นได้ชัดสำหรับการอ่านพร้อมกันแม้ในขณะที่การแก้ไขพร้อมกันกำลังดำเนินต่อไป - ไม่ว่าจะใช้เวลานานเท่าใด
- เพราะ "สแนปช็อต" เป็นสิ่งที่เปลี่ยนไม่ได้ล็อคมิคแบบ atomicityกล่าวคือ
var snap = _list; snap[snap.Count - 1];
จะไม่ (ดียกเว้นรายการที่ว่างเปล่าของหลักสูตร) และคุณยังได้รับการแจงนับข้อความที่ปลอดภัยด้วย semantics สแนปช็อตฟรี ..
- ดำเนินการโดยทั่วไปใช้กับโครงสร้างข้อมูลใด ๆและชนิดของการปรับเปลี่ยนใด ๆ
- ง่ายตายคือง่ายต่อการทดสอบตรวจแก้จุดบกพร่องตรวจสอบโดยการอ่านรหัส
- ใช้งานได้ใน. Net 3.5
เพื่อให้การคัดลอกไปทำงานคุณต้องเก็บโครงสร้างข้อมูลของคุณ ไม่เปลี่ยนรูปได้อย่างมีประสิทธิภาพนั่นคือไม่มีใครได้รับอนุญาตให้เปลี่ยนโครงสร้างหลังจากที่คุณทำให้มันพร้อมใช้งานกับเธรดอื่น เมื่อคุณต้องการแก้ไขคุณ
- โคลนโครงสร้าง
- ทำการแก้ไขบนโคลน
- แลกเปลี่ยนอะตอมในการอ้างอิงถึงโคลนดัดแปลง
รหัส
static class CopyOnWriteSwapper
{
public static void Swap<T>(ref T obj, Func<T, T> cloner, Action<T> op)
where T : class
{
while (true)
{
var objBefore = Volatile.Read(ref obj);
var newObj = cloner(objBefore);
op(newObj);
if (Interlocked.CompareExchange(ref obj, newObj, objBefore) == objBefore)
return;
}
}
}
การใช้
CopyOnWriteSwapper.Swap(ref _myList,
orig => new List<string>(orig),
clone => clone.Add("asdf"));
หากคุณต้องการประสิทธิภาพที่เพิ่มขึ้นมันจะช่วยแยกวิธีการเช่นสร้างวิธีการหนึ่งสำหรับการแก้ไขทุกประเภท (เพิ่ม, ลบ, ... ) ที่คุณต้องการและรหัสยากสำหรับพอยน์เตอร์ของฟังก์ชันcloner
และop
และ
NB # 1มันเป็นความรับผิดชอบของคุณเพื่อให้แน่ใจว่าไม่มีใครแก้ไขโครงสร้างข้อมูลที่ไม่เปลี่ยนรูปแบบ (สมมุติ) ไม่มีสิ่งใดที่เราสามารถทำได้ในการนำไปใช้ทั่วไปเพื่อป้องกันสิ่งนั้น แต่เมื่อเชี่ยวชาญList<T>
คุณสามารถป้องกันการเปลี่ยนแปลงโดยใช้ List.AsReadOnly ()
NB # 2ระมัดระวังเกี่ยวกับค่าในรายการ วิธีการคัดลอกเมื่อเขียนข้างต้นจะป้องกันความเป็นสมาชิกรายการของพวกเขาเท่านั้น แต่ถ้าคุณไม่ใส่สตริง แต่วัตถุที่ไม่แน่นอนอื่น ๆ ในนั้นคุณต้องดูแลความปลอดภัยของเธรด (เช่นการล็อค) แต่นั่นคือมุมฉากของการแก้ปัญหานี้และเช่นการล็อคค่าที่ไม่แน่นอนสามารถใช้งานได้ง่ายโดยไม่มีปัญหา คุณเพียงแค่ต้องระวัง
NB # 3หากโครงสร้างข้อมูลของคุณมีขนาดใหญ่มากและคุณแก้ไขบ่อยวิธีการคัดลอกทั้งหมดเมื่อเขียนอาจเป็นสิ่งต้องห้ามทั้งในแง่ของปริมาณการใช้หน่วยความจำและค่าใช้จ่าย CPU ในการคัดลอกที่เกี่ยวข้อง ในกรณีดังกล่าวคุณอาจต้องการใช้คอลเล็กชันที่ไม่เปลี่ยนรูปแบบของ MS แทน