Lock กับ Mutex ต่างกันอย่างไร?


คำตอบ:



96

lockเป็นคีย์เวิร์ดคอมไพเลอร์ไม่ใช่คลาสหรืออ็อบเจ็กต์จริง เป็นกระดาษห่อหุ้มฟังก์ชันการทำงานของMonitorคลาสและออกแบบมาเพื่อให้ใช้งานMonitorได้ง่ายขึ้นสำหรับกรณีทั่วไป

Monitor(และlockคำหลัก) จะเป็นดารินทร์กล่าวว่าถูก จำกัด AppDomainไปยัง ส่วนใหญ่เนื่องจากจำเป็นต้องมีการอ้างอิงไปยังที่อยู่หน่วยความจำ (ในรูปแบบของวัตถุที่สร้างอินสแตนซ์) เพื่อจัดการ "ล็อก" และรักษาข้อมูลประจำตัวของMonitor

Mutexบนมืออื่น ๆ ที่เป็นกระดาษห่อสุทธิรอบสร้างระบบปฏิบัติการและสามารถนำมาใช้สำหรับการประสานทั้งระบบโดยใช้สตริงข้อมูล (แทนตัวชี้ไปยังข้อมูล) เป็นตัวระบุ mutexes สองตัวที่อ้างอิงสองสตริงในที่อยู่หน่วยความจำสองที่แตกต่างกันโดยสิ้นเชิง แต่มีข้อมูลเดียวกันจะใช้ mutex ระบบปฏิบัติการเดียวกัน


54

Mutexสามารถทั้งในท้องถิ่นเพื่อเป็นกระบวนการหรือทั้งระบบ MSDN :

Mutexes มีสองประเภท: mutexes แบบโลคัลซึ่งไม่มีชื่อและตั้งชื่อระบบ mutexes mutex ในเครื่องมีอยู่ในกระบวนการของคุณเท่านั้น

นอกจากนี้ควรใช้ความระมัดระวังเป็นพิเศษ - มีรายละเอียดอยู่ในหน้าเดียวกันเช่นกัน - เมื่อใช้ mutex ทั้งระบบบนระบบที่มี Terminal Services

ความแตกต่างอย่างหนึ่งระหว่างMutexและlockคือการMutexใช้โครงสร้างระดับเคอร์เนลดังนั้นการซิงโครไนซ์จะต้องมีการเปลี่ยนพื้นที่เคอร์เนลของผู้ใช้เป็นอย่างน้อย

lock- นั่นเป็นทางลัดไปสู่Monitorคลาสในทางกลับกันพยายามหลีกเลี่ยงการจัดสรรทรัพยากรเคอร์เนลและการเปลี่ยนไปใช้รหัสเคอร์เนล (และมีขนาดเล็กลงและเร็วขึ้น - หากต้องหาโครงสร้าง WinAPI ที่มีลักษณะคล้ายกันก็จะเป็นได้CriticalSection)

ความแตกต่างอื่น ๆ คือสิ่งที่ผู้อื่นชี้ให้เห็น: ชื่อ Mutex สามารถใช้ข้ามกระบวนการได้

เว้นแต่จะมีความต้องการพิเศษหรือต้องการการซิงโครไนซ์ระหว่างกระบวนการก็จะดีกว่าที่จะยึดติดกับlock(akaMonitor ) ˛

มีความแตกต่าง "เล็กน้อย" อื่น ๆ อีกหลายประการเช่นวิธีจัดการกับการละทิ้งเป็นต้น

เช่นเดียวกับที่ได้กล่าวเกี่ยวกับReaderWriterLockและReaderWriterLockSlimใน 3.5 Semaphoreและใหม่SemaphoreSlimใน .NET 4.0 ฯลฯ มันเป็นความจริงว่าหลังxxSlimเรียนไม่สามารถใช้เป็นทั้งระบบพื้นฐานซิงค์ แต่พวกเขาก็ไม่เคยหมายถึง - พวกเขาได้ "เท่านั้น" หมายความว่า เพื่อให้เร็วขึ้นและเป็นมิตรกับทรัพยากรมากขึ้น


25

ฉันใช้ Mutex เพื่อตรวจสอบว่าฉันมีสำเนาของแอปพลิเคชันที่ทำงานบนเครื่องเดียวกันหรือไม่

bool firstInstance;
Mutex mutex = new Mutex(false, @"Local\DASHBOARD_MAIN_APPLICATION", out firstInstance);

if (!firstInstance)
{
    //another copy of this application running 
}
else
{
    //run main application loop here.
}
// Refer to the mutex down here so garbage collection doesn't chuck it out.
GC.KeepAlive(mutex);

8

มีคนพูดไปแล้วมากมาย แต่เพื่อให้ง่ายนี่คือสิ่งที่ฉันใช้

ล็อค -> ใช้งานง่ายกระดาษห่อหุ้มบนจอภาพล็อคข้ามเธรดใน AppDomain

mutex ที่ไม่มีชื่อ -> คล้ายกับการล็อกยกเว้นขอบเขตการล็อกมีมากกว่าและอยู่ใน AppDomain ในกระบวนการ

ชื่อว่า mutex -> ขอบเขตการล็อกเป็นมากกว่า mutex ที่ไม่มีชื่อและอยู่ระหว่างกระบวนการในระบบปฏิบัติการ

ตอนนี้มีตัวเลือกแล้วคุณต้องเลือกตัวเลือกที่เหมาะสมที่สุดในกรณีของคุณ


ตามที่ฉันเข้าใจจากคำตอบและตัวอย่างสำหรับ mutex ที่นี่msdn.microsoft.com/en-us/library/… : mutex ที่ไม่มีชื่อทำหน้าที่เหมือนกับการล็อก อย่างไรก็ตาม mutex.WaitOne (1000) ทำให้เรามีโอกาสหมดเวลาล็อก ในทางกลับกัน Monitor.TryEnter ยังให้ความสามารถนั้นแก่เรา ดังที่กล่าวไว้ Mutex เป็นกระดาษห่อหุ้ม ดังนั้นฉันจะใช้ล็อคหรือ Monitor แทน mutex ที่ไม่มีชื่อ แต่ถ้าจำเป็นต้องมีการล็อกข้ามกระบวนการชื่อ mutex คือหนทางที่จะไป กรุณาแก้ไขฉันถ้าฉันผิด
Koray

6

Mutex เป็นกระบวนการข้ามและจะมีตัวอย่างคลาสสิกของการไม่เรียกใช้แอปพลิเคชันมากกว่าหนึ่งอินสแตนซ์

ตัวอย่างที่ 2 คือบอกว่าคุณมีไฟล์และไม่ต้องการให้กระบวนการอื่นเข้าถึงไฟล์เดียวกันคุณสามารถใช้งาน Mutex ได้ แต่จำไว้ว่าสิ่งหนึ่งที่ Mutex เป็นระบบปฏิบัติการที่กว้างและไม่สามารถใช้ระหว่างสองกระบวนการระยะไกลได้

การล็อกเป็นวิธีที่ง่ายที่สุดในการป้องกันส่วนของรหัสของคุณและเป็นโดเมนเฉพาะของแอปคุณสามารถแทนที่การล็อกด้วยจอภาพได้หากต้องการการซิงโครไนซ์ที่ควบคุมได้มากขึ้น


1

ความแตกต่างเล็กน้อยอีกเล็กน้อยที่ไม่ได้กล่าวถึงในคำตอบ:

  1. ในกรณีที่ใช้ล็อคคุณสามารถมั่นใจได้ว่าจะล็อค คลายเมื่อมีข้อยกเว้นเกิดขึ้นภายในบล็อกของล็อก
    นั่นเป็นเพราะการล็อคใช้จอภาพใต้ฝากระโปรงและใช้วิธีนี้ :

     object __lockObj = x;
     bool __lockWasTaken = false;
     try
     {
         System.Threading.Monitor.Enter(__lockObj, ref __lockWasTaken);
         // Your code...
     }
     finally
     {
         if (__lockWasTaken) System.Threading.Monitor.Exit(__lockObj);
     }

    ดังนั้นไม่ว่าในกรณีใดล็อคจะถูกปลดและคุณไม่จำเป็นต้องปลดล็อคด้วยตนเอง (เช่นเดียวกับที่คุณทำกับ mutexes)

  2. สำหรับ Locks คุณมักจะใช้วัตถุส่วนตัวเพื่อล็อค (และควรใช้ )
    นี้ทำด้วยเหตุผลหลายประการ (ข้อมูลเพิ่มเติม:ดูคำตอบนี้และเอกสารอย่างเป็นทางการ )

ดังนั้นในกรณีของการล็อกคุณจะไม่สามารถ (เข้าถึงวัตถุที่ถูกล็อกจากภายนอกโดยบังเอิญ) และทำให้เกิดความเสียหายได้
แต่ในกรณีของ Mutex คุณสามารถทำได้เนื่องจากเป็นเรื่องปกติที่จะมี Mutex ซึ่งทำเครื่องหมายเป็นสาธารณะและใช้งานได้จากทุกที่

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.