บางคนสามารถอธิบายความแตกต่างระหว่าง:
- ล็อค (someobject) {}
- ใช้ Mutex
- ใช้เซมาฟอร์
- ใช้การตรวจสอบ
- ใช้คลาสการซิงโครไนซ์. Net อื่น ๆ
ฉันแค่คิดออกไม่ได้ ดูเหมือนว่าฉันสองคนแรกเหมือนกันหรือไม่
บางคนสามารถอธิบายความแตกต่างระหว่าง:
ฉันแค่คิดออกไม่ได้ ดูเหมือนว่าฉันสองคนแรกเหมือนกันหรือไม่
คำตอบ:
เป็นคำถามที่ดีมาก ฉันอาจผิด .. ให้ฉันลอง .. แก้ไข # 2 ของคำตอบต้นกำเนิดของฉัน .. ด้วยความเข้าใจเพิ่มขึ้นเล็กน้อย ขอบคุณที่ทำให้ฉันอ่าน :)
ล็อค (obj)
จอภาพ
การใช้การล็อกหรือมอนิเตอร์มีประโยชน์ในการป้องกันการดำเนินการบล็อกของเธรดที่มีความอ่อนไหวของรหัส แต่การสร้างเหล่านี้ไม่อนุญาตให้เธรดหนึ่งสื่อสารเหตุการณ์ไปยังอีกเธรดหนึ่ง สิ่งนี้ต้องการเหตุการณ์การซิงโครไนซ์ซึ่งเป็นวัตถุที่มีสถานะหนึ่งในสองสถานะสัญญาณและไม่ส่งสัญญาณซึ่งสามารถใช้เพื่อเปิดใช้งานและระงับเธรด Mutex, Semaphores เป็นแนวคิดระดับ OS เช่นด้วย mutex ที่มีชื่อคุณสามารถซิงโครไนซ์กับ exes (ที่มีการจัดการ) หลายรายการได้
mutex:
Semaphores (ทำร้ายสมองฉัน)
Monitor
ไม่อนุญาตการสื่อสารที่ไม่ถูกต้อง คุณยังสามารถPulse
ฯลฯ ด้วยMonitor
เรื่อง "การใช้คลาสการซิงโครไนซ์. Net อื่น ๆ " - อันอื่น ๆ ที่คุณควรทราบเกี่ยวกับ:
นอกจากนี้ยังมีโครงสร้างการล็อกเพิ่มเติม (ค่าโสหุ้ยต่ำ) ใน CCR / TPL ( Parallel Extensions CTP) - แต่ IIRC เหล่านี้จะพร้อมใช้งานใน. NET 4.0
ตามที่ระบุไว้ใน ECMA และตามที่คุณสามารถสังเกตได้จากวิธีการที่สะท้อนคำสั่งล็อคนั้นเทียบเท่ากับ
object obj = x;
System.Threading.Monitor.Enter(obj);
try {
…
}
finally {
System.Threading.Monitor.Exit(obj);
}
จากตัวอย่างข้างต้นเราจะเห็นว่าจอภาพสามารถล็อควัตถุได้
Mutexe นั้นมีประโยชน์เมื่อคุณต้องการซิงโครไนซ์การประมวลผลเนื่องจากสามารถล็อกตัวระบุสตริงได้ ตัวระบุสตริงเดียวกันสามารถใช้โดยกระบวนการต่าง ๆ เพื่อรับการล็อก
Semaphores เหมือนกับ Mutexes บนเตียรอยด์พวกมันอนุญาตการเข้าถึงพร้อมกันโดยการนับจำนวนสูงสุดของการเข้าถึงพร้อมกัน ' เมื่อถึงขีด จำกัด สัญญาณจะเริ่มบล็อกการเข้าถึงทรัพยากรใด ๆ เพิ่มเติมจนกว่าจะมีผู้เรียกหนึ่งรายปล่อยสัญญาณ
ฉันได้เรียน & CLR เพื่อสนับสนุนเธรดใน DotGNU และฉันมีความคิดเล็กน้อย ...
นอกจากว่าคุณต้องการล็อคข้ามกระบวนการคุณควรหลีกเลี่ยงการใช้ Mutex & Semaphores คลาสเหล่านี้ใน. NET เป็นตัวล้อมรอบ Win32 Mutex และ Semaphores และมีน้ำหนักค่อนข้างมาก (พวกเขาต้องการสลับบริบทเป็นเคอร์เนลซึ่งมีราคาแพง - โดยเฉพาะอย่างยิ่งถ้าล็อคของคุณไม่อยู่ภายใต้การช่วงชิง)
ตามที่คนอื่นพูดถึงคำสั่ง C # lock นั้นเป็นเวทย์มนตร์คอมไพเลอร์สำหรับ Monitor.Enter และ Monitor.Exit (มีอยู่ภายในลอง / ในที่สุด)
จอภาพมีกลไกสัญญาณ / รอที่เรียบง่าย แต่ทรงพลังซึ่ง Mutexes ไม่มีผ่านทางวิธี Monitor.Pulse / Monitor.Wait Win32 ที่เทียบเท่ากันจะเป็นวัตถุเหตุการณ์ผ่าน CreateEvent ซึ่งจริง ๆ แล้วมีอยู่ใน. NET เป็น WaitHandles รูปแบบ Pulse / Wait นั้นคล้ายกับ pthread_signal และ pthread_wait ของ Unix แต่เร็วกว่าเพราะสามารถใช้งานในโหมดผู้ใช้ทั้งหมดในกรณีที่ไม่ได้โต้แย้ง
Monitor.Pulse / Wait นั้นใช้ง่าย ในหนึ่งเธรดเราล็อกวัตถุตรวจสอบค่าสถานะ / สถานะ / คุณสมบัติและถ้าไม่ใช่สิ่งที่เราคาดหวังเรียก Monitor.Wait ซึ่งจะปล่อยล็อกและรอจนกว่าจะส่งชีพจร เมื่อการรอกลับมาเราจะวนกลับและตรวจสอบการตั้งค่าสถานะ / สถานะ / อีกครั้ง ในเธรดอื่นเราล็อกวัตถุเมื่อใดก็ตามที่เราเปลี่ยนค่าสถานะ / สถานะ / คุณสมบัติแล้วเรียก PulseAll เพื่อปลุกเธรดการฟังใด ๆ
บ่อยครั้งที่เราต้องการให้คลาสของเราปลอดภัยสำหรับเธรดดังนั้นเราจึงใส่รหัสล็อคไว้ในโค้ด อย่างไรก็ตามบ่อยครั้งที่คลาสของเราจะใช้เพียงเธรดเดียวเท่านั้น ซึ่งหมายความว่าการล็อกจะทำให้โค้ดของเราช้าลงโดยไม่จำเป็น ... นี่คือที่การเพิ่มประสิทธิภาพที่ชาญฉลาดใน CLR สามารถช่วยปรับปรุงประสิทธิภาพได้
ฉันไม่แน่ใจเกี่ยวกับการใช้งานการล็อกของ Microsoft แต่ใน DotGNU และ Mono การตั้งค่าสถานะการล็อคถูกเก็บไว้ในส่วนหัวของวัตถุทุกรายการ วัตถุทุกชิ้นใน. NET (และ Java) สามารถล็อคได้ดังนั้นทุกวัตถุต้องรองรับสิ่งนี้ในส่วนหัว ในการปรับใช้ DotGNU จะมีการตั้งค่าสถานะที่อนุญาตให้คุณใช้ hashtable ทั่วโลกสำหรับทุกวัตถุที่ใช้เป็นตัวล็อกซึ่งจะเป็นประโยชน์ในการกำจัดโอเวอร์เฮด 4 ไบต์สำหรับทุกวัตถุ สิ่งนี้ไม่ดีสำหรับหน่วยความจำ (โดยเฉพาะอย่างยิ่งสำหรับระบบฝังตัวที่ไม่ได้มีเธรดมาก) แต่ได้รับความนิยมอย่างมากในประสิทธิภาพ
ทั้ง Mono และ DotGNU ใช้ mutexes อย่างมีประสิทธิภาพในการล็อก / รอ แต่ใช้การดำเนินการเปรียบเทียบและแลกเปลี่ยนสไตล์ spinlock เพื่อขจัดความจำเป็นในการใช้งานการล็อกแบบ hard จริง ๆ เว้นแต่จำเป็นจริงๆ:
คุณสามารถดูตัวอย่างวิธีการใช้งานจอภาพได้ที่นี่:
http://cvs.savannah.gnu.org/viewvc/dotgnu-pnet/pnet/engine/lib_monitor.c?revision=1.7&view=markup
ข้อควรระวังเพิ่มเติมสำหรับการล็อค Mutex ที่คุณระบุด้วย ID สตริงนั้นจะเป็นค่าเริ่มต้นเป็น Mutex "Local \" และจะไม่ถูกแชร์ข้ามเซสชันในสภาพแวดล้อมของเทอร์มินัลเซิร์ฟเวอร์
คำนำหน้าตัวระบุสตริงของคุณด้วย "Global \" เพื่อให้แน่ใจว่ามีการควบคุมการเข้าถึงทรัพยากรระบบที่ใช้ร่วมกันอย่างเหมาะสม ฉันเพิ่งพบเจอกับปัญหาทั้งหมดที่ประสานการสื่อสารกับบริการที่ทำงานภายใต้บัญชี SYSTEM ก่อนที่ฉันจะรู้ตัว
ฉันจะพยายามหลีกเลี่ยง "lock ()", "Mutex" และ "Monitor" หากคุณสามารถ ...
ลองใช้เนมสเปซใหม่ System.Collections.Concurrent ใน. NET 4
มันมีคลาสคอลเลกชันเซฟเธรดที่ดี
http://msdn.microsoft.com/en-us/library/system.collections.concurrent.aspx
หินพร้อมกันพจนานุกรม! ไม่มีการล็อคด้วยตนเองอีกต่อไปสำหรับฉัน!
ในกรณีส่วนใหญ่คุณไม่ควรใช้ล็อค (= จอภาพ) หรือ mutexes / semaphores พวกเขาทั้งหมดบล็อกเธรดปัจจุบัน
และคุณไม่ควรใช้ System.Collections.Concurrent
คลาสแน่นอน- มันเป็นแหล่งที่มาหลักของเงื่อนไขการแข่งขันเพราะไม่รองรับธุรกรรมระหว่างหลายคอลเลกชันและยังบล็อกเธรดปัจจุบัน
น่าแปลกที่. NET ไม่มีกลไกที่มีประสิทธิภาพสำหรับการซิงโครไนซ์
ฉันใช้คิวอนุกรมจาก GCD ( Objc/Swift
โลก) ใน C # - มีน้ำหนักเบามากไม่บล็อกเครื่องมือซิงโครไนซ์ที่ใช้เธรดพูลพร้อมการทดสอบ
เป็นวิธีที่ดีที่สุดในการซิงโครไนซ์ทุกอย่างในกรณีส่วนใหญ่ - จากการเข้าถึงฐานข้อมูล (สวัสดี sqlite) ถึงตรรกะทางธุรกิจ