Mutex คืออะไร


653

mutex เป็นแนวคิดการเขียนโปรแกรมที่ใช้บ่อยในการแก้ปัญหาหลายเธรด คำถามของฉันต่อชุมชน:

Mutex คืออะไรและคุณใช้มันอย่างไร


2
นี่เป็นบทความที่ดีเกี่ยวกับความแตกต่าง: barrgroup.com/Embedded-Systems/How-To/RTOS-Mutex-Semaphore
Adam Davis

การสอนเกี่ยวกับ mutex สามารถช่วยล้างสิ่งต่าง ๆ ได้: stackoverflow.com/questions/4989451/mutex-example-tutorial
Nav

1
Mutex เป็นเหมือนกุญแจห้องน้ำที่ปั๊มน้ำมันเพื่อให้แน่ใจว่ามีเพียงคนเดียวเท่านั้นที่สามารถใช้ห้องน้ำได้ตลอดเวลาและไม่มีใครสามารถใช้ห้องน้ำจนกว่าผู้ครอบครองปัจจุบันจะเสร็จสิ้นและส่งคืนกุญแจ
jonschlinkert

คำตอบ:


2152

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

แทนที่ Chicken ด้วย Mutex และบุคคลที่มี thread และโดยทั่วไปคุณมีแนวคิดของ mutex

แน่นอนไม่มีสิ่งเช่น mutex ยาง ไก่ยางเท่านั้น แมวของฉันเคยมีหนูยาง แต่พวกเขากินมัน

แน่นอนว่าก่อนที่คุณจะใช้ไก่ยางพาราคุณต้องถามตัวเองว่าคุณต้องการ 5 คนในห้องจริงหรือไม่และจะง่ายกว่าถ้ามีคนคนหนึ่งอยู่ในห้องด้วยตนเอง จริงๆแล้วนี่เป็นการขยายความคล้ายคลึงกัน แต่คุณจะได้ความคิด


9
คำตอบที่ดี มันอาจจะเป็นที่ถกเถียงกันอยู่ว่า Mutex เป็นกฎที่ห้ามไก่ผ่านหรือไม่ และไก่เป็นสิ่งที่คุณล็อค?
SirYakalot

3
@SirYakalot คุณหมายถึงไก่เป็นทรัพยากรและผู้ดำเนินรายการคือ mutex หรือไม่
โอเว่น

156
ไก่เป็นmutex คน hoilding หมู่ .. ไก่มีการแข่งขันหัวข้อ ผู้ดูแลเป็นOS เมื่อมีคนร้องขอไก่พวกเขาจะขอล็อค เมื่อคุณเรียก mutex.lock () เธรดของคุณจะค้างในล็อค () และทำการร้องขอการล็อกไปยังระบบปฏิบัติการ เมื่อระบบปฏิบัติการตรวจพบว่า mutex ถูกปล่อยจากเธรดมันจะมอบให้กับคุณเท่านั้นและจะส่งกลับค่า lock () - mutex จะกลายเป็นของคุณและของคุณเท่านั้น ไม่มีใครสามารถขโมยได้เพราะการเรียก lock () จะบล็อกเขา นอกจากนี้ยังมี try_lock () ที่จะบล็อกและคืนค่าจริงเมื่อ mutex เป็นของคุณและเป็นเท็จทันทีหากมีการใช้ mutex
ПетърПетров

4
คุณเป็นอัจฉริยะ คุณสามารถใช้อุปมายางไก่เพื่ออธิบายจอภาพได้หรือไม่
Riccardo

98
บางครั้งที่มาของแนวคิดการเขียนโปรแกรมบางอย่างไม่ชัดเจน มือใหม่อาจจะสงสัยว่าทำไมทุกคนพูดถึง regex ไม่ชัดเจนว่า regex สั้นสำหรับ [reg] ular [ex] pression ทำนองเดียวกัน mutex ย่อมาจาก [mut] ual [ex] clusion สิ่งนี้อาจทำให้ความหมายของคำย่อยง่ายขึ้น @TheSmurf เชื่อมโยงกับมันในคำตอบของพวกเขา แต่มันอาจจะดีที่จะเพิ่มไว้ที่นี่เพื่อวัตถุประสงค์ทางประวัติศาสตร์
Dodzi Dzakuma

137

Mutex เป็นแฟล็กที่ไม่เกิดร่วมกัน มันทำหน้าที่เป็นผู้รักษาประตูไปยังส่วนของรหัสที่อนุญาตให้หนึ่งเธรดในและปิดกั้นการเข้าถึงอื่น ๆ ทั้งหมด สิ่งนี้ทำให้มั่นใจได้ว่าโค้ดที่ถูกควบคุมจะถูกโจมตีด้วยเธรดครั้งละหนึ่งรายการเท่านั้น เพียงให้แน่ใจว่าจะปล่อย mutex เมื่อคุณทำเสร็จแล้ว :)


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

72

การยกเว้นซึ่งกันและกัน นี่คือรายการ Wikipedia ที่มัน:

http://en.wikipedia.org/wiki/Mutual_exclusion

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

รายละเอียดเฉพาะของวิธีการที่จะประสบความสำเร็จอย่างเห็นได้ชัดนั้นแตกต่างกันอย่างมากตามภาษาการเขียนโปรแกรม


65

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

แนวคิดนี้เรียกว่า "การยกเว้นร่วมกัน" (Mutex แบบสั้น) และเป็นวิธีการตรวจสอบให้แน่ใจว่าอนุญาตให้มีเธรดเดียวเท่านั้นภายในพื้นที่นั้นโดยใช้ทรัพยากรนั้นเป็นต้น

วิธีใช้เป็นเฉพาะภาษา แต่มักจะ (ถ้าไม่เสมอ) ตามระบบปฏิบัติการ mutex

บางภาษาไม่ต้องการโครงสร้างนี้เนื่องจากกระบวนทัศน์ตัวอย่างเช่นการเขียนโปรแกรมใช้งานได้ (Haskell, ML เป็นตัวอย่างที่ดี)


26

ใน C # ที่ mutex ทั่วไปที่ใช้คือการตรวจสอบ ประเภทคือ ' System.Threading.Monitor ' มันอาจถูกนำมาใช้โดยนัยผ่านคำสั่ง ' lock (Object) ' ตัวอย่างหนึ่งของการใช้งานคือเมื่อสร้างคลาส Singleton

private static readonly Object instanceLock = new Object();
private static MySingleton instance;
public static MySingleton Instance
{
    lock(instanceLock)
    {
        if(instance == null)
        {
            instance = new MySingleton();
        }
        return instance;
    }
}

คำสั่งล็อคโดยใช้วัตถุล็อคส่วนตัวสร้างส่วนที่สำคัญ ต้องการให้แต่ละเธรดรอจนกว่าก่อนหน้านี้จะเสร็จสิ้น เธรดแรกจะเข้าสู่ส่วนและเริ่มต้นอินสแตนซ์ เธรดที่สองจะรอรับในส่วนและรับอินสแตนซ์ที่เตรียมใช้งาน

การซิงโครไนซ์ประเภทใด ๆ ของสมาชิกแบบสแตติกอาจใช้คำสั่งล็อคในทำนองเดียวกัน


1
นี่คือคำตอบที่ขึ้นอยู่กับการใช้งาน นอกจากนี้ใน CS มอนิเตอร์จะแตกต่างจาก mutex จอภาพมีกลไกการซิงโครไนซ์ แต่ mutex เพียงแค่ล็อกสิ่งจนกว่าจะไม่ต้องการอีกต่อไป IDK เกี่ยวกับรายละเอียดการติดตั้งใช้งานหรือซีแมนทิกส์ C # แต่ฉันคิดว่าบริบทของคำถามนั้นกว้างกว่า
marcoslhc

24

คืออะไรMutex ?

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

คืออะไรการแข่งขันสภาพ ?

สภาวะการแย่งชิงเกิดขึ้นเมื่อสองกระทู้หรือมากกว่าสามารถเข้าถึงข้อมูลที่ใช้ร่วมกันและพวกเขาพยายามที่จะเปลี่ยนมันในเวลาเดียวกัน เนื่องจากอัลกอริทึมการตั้งเวลาเธรดสามารถสลับระหว่างเธรดได้ตลอดเวลาคุณไม่ทราบลำดับที่เธรดจะพยายามเข้าถึงข้อมูลที่แชร์ ดังนั้นผลลัพธ์ของการเปลี่ยนแปลงข้อมูลจึงขึ้นอยู่กับอัลกอริทึมการจัดตารางเวลาเธรดนั่นคือทั้งสองเธรดคือ "การแข่ง" เพื่อเข้าถึง / เปลี่ยนแปลงข้อมูล

ตัวอย่างชีวิตจริง:

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

แทนที่ Chicken ด้วย Mutex และบุคคลที่มี thread และโดยทั่วไปคุณมีแนวคิดของ mutex

@Xetius

การใช้งานใน C #:

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

using System;
using System.Threading;

class Example
{
    // Create a new Mutex. The creating thread does not own the mutex.
    private static Mutex mut = new Mutex();
    private const int numIterations = 1;
    private const int numThreads = 3;

    static void Main()
    {
        // Create the threads that will use the protected resource.
        for(int i = 0; i < numThreads; i++)
        {
            Thread newThread = new Thread(new ThreadStart(ThreadProc));
            newThread.Name = String.Format("Thread{0}", i + 1);
            newThread.Start();
        }

        // The main thread exits, but the application continues to
        // run until all foreground threads have exited.
    }

    private static void ThreadProc()
    {
        for(int i = 0; i < numIterations; i++)
        {
            UseResource();
        }
    }

    // This method represents a resource that must be synchronized
    // so that only one thread at a time can enter.
    private static void UseResource()
    {
        // Wait until it is safe to enter.
        Console.WriteLine("{0} is requesting the mutex", 
                          Thread.CurrentThread.Name);
        mut.WaitOne();

        Console.WriteLine("{0} has entered the protected area", 
                          Thread.CurrentThread.Name);

        // Place code to access non-reentrant resources here.

        // Simulate some work.
        Thread.Sleep(500);

        Console.WriteLine("{0} is leaving the protected area", 
            Thread.CurrentThread.Name);

        // Release the Mutex.
        mut.ReleaseMutex();
        Console.WriteLine("{0} has released the mutex", 
            Thread.CurrentThread.Name);
    }
}
// The example displays output like the following:
//       Thread1 is requesting the mutex
//       Thread2 is requesting the mutex
//       Thread1 has entered the protected area
//       Thread3 is requesting the mutex
//       Thread1 is leaving the protected area
//       Thread1 has released the mutex
//       Thread3 has entered the protected area
//       Thread3 is leaving the protected area
//       Thread3 has released the mutex
//       Thread2 has entered the protected area
//       Thread2 is leaving the protected area
//       Thread2 has released the mutex

Mutex อ้างอิง MSDN


1
เป็นตัวอย่างที่ดีมาก
Siwei Shen 申思维

22

มีคำตอบที่ยอดเยี่ยมอยู่ที่นี่นี่เป็นอีกการเปรียบเทียบที่ยอดเยี่ยมสำหรับการอธิบายว่าmutexคืออะไร:

พิจารณาเดียวห้องน้ำมีที่สำคัญ เมื่อมีคนเข้าพวกเขาใช้เวลาที่สำคัญและห้องน้ำอยู่ในครอบครอง ถ้ามีคนอื่นที่จะตอบสนองความต้องการใช้ห้องน้ำที่พวกเขาจำเป็นต้องรอในคิว เมื่อบุคคลในห้องน้ำเสร็จแล้วพวกเขาจะส่งกุญแจไปยังบุคคลต่อไปในคิว เข้าท่าใช่ไหม?

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


แต่ตัวอย่าง c # ไม่สนับสนุนการยืนยันคิวของคุณ "ส่งคีย์ไปยังบุคคลต่อไปในคิว" ตัวอย่างกำลังสาธิตสแต็กหรือสุ่ม 1, 2 และ 3 เข้าถึงการร้องขอทั้งหมดตามลำดับนั้น อนุญาตให้หนึ่งอันแรกเข้าไปในพื้นที่คุ้มครองจากนั้นอนุญาตสามแห่ง คิวจะให้มันกับวินาที
donvnielsen

ฉันไม่ได้หมายถึงการใช้งานที่เป็นรูปธรรมหรือภาษาการเขียนโปรแกรมที่เป็นรูปธรรม ตัวอย่างของฉันเกี่ยวข้องกับสิ่งที่เป็นนามธรรมในระดับสูงของ mutex เป็นหลักการ
เฉิน A.

18

ในการทำความเข้าใจกับ MUTEX ในตอนแรกคุณต้องรู้ว่า "สภาพการแข่งขัน" คืออะไรและจากนั้นมีเพียงคุณเท่านั้นที่จะเข้าใจว่าทำไมจึงต้องมี MUTEX สมมติว่าคุณมีโปรแกรมหลายเธรดและคุณมีสองเธรด ตอนนี้คุณมีงานหนึ่งงานในคิวงาน เธรดแรกจะตรวจสอบคิวงานและหลังจากหางานมันจะเริ่มดำเนินการ เธรดที่สองจะตรวจสอบคิวงานและพบว่ามีหนึ่งงานในคิว ดังนั้นมันจะกำหนดตัวชี้งานเดียวกัน ดังนั้นตอนนี้จะเกิดอะไรขึ้นเธรดทั้งคู่กำลังดำเนินงานเดียวกัน สิ่งนี้จะทำให้เกิดการแบ่งกลุ่มผิดพลาด นี่คือตัวอย่างของสภาพการแข่งขัน

การแก้ไขปัญหานี้คือ MUTEX MUTEX เป็นล็อคชนิดหนึ่งที่ล็อคทีละหนึ่งเธรด หากเธรดอื่นต้องการล็อคเธรดก็จะถูกบล็อก

หัวข้อ MUTEX ในลิงค์ไฟล์ pdfนี้คุ้มค่าที่จะอ่าน


โดย "หัวข้อ MUTEX" คุณหมายถึงส่วนของเซมาฟอร์เพราะตัวอย่างของมันเป็นเซมาฟอร์ไบนารีใช่ไหม?
Carl G

2
Mutex เป็นเพียงเซมาฟอร์ที่มีค่า 1
marcoslhc

หนังสือเล่มใดในบทนี้ที่คุณแบ่งปัน? ได้โปรด
Omar Faroque Anik

@OmarFaroqueAnik หนังสืออ้างอิงคือการเขียนโปรแกรม Linux ขั้นสูงโดย CodeSourcery LLC จัดพิมพ์โดย New Riders Publishing และสามารถเข้าถึงได้จากหน้าแรกของโดเมนที่เชื่อมโยง
RMart

11

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


เป็นเรื่องจริงเหรอ? กระบวนการแต่ละรายการจะสร้างสำเนา mutex ของตนเองหรือไม่
Leon

0

Mutex: Mutex ย่อมาจากMut ual Ex clusion มันหมายความว่าในเวลาหนึ่งกระบวนการ / เธรดสามารถเข้าสู่ส่วนที่สำคัญ ในการเขียนโปรแกรมพร้อมกันที่หลายเธรด / กระบวนการพยายามอัปเดตทรัพยากรที่ใช้ร่วมกัน (ตัวแปรใด ๆ , หน่วยความจำที่แชร์ ฯลฯ ) อาจทำให้เกิดผลลัพธ์ที่ไม่คาดคิด (เนื่องจากผลลัพธ์ขึ้นอยู่กับเธรด / กระบวนการที่ได้รับสิทธิ์เข้าถึงครั้งแรก)

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

ไลบรารี pthread ให้การสนับสนุน Mutex

typedef union
{
  struct __pthread_mutex_s
  {
    ***int __lock;***
    unsigned int __count;
    int __owner;
#ifdef __x86_64__
    unsigned int __nusers;
#endif
 int __kind;
#ifdef __x86_64__
    short __spins;
    short __elision;
    __pthread_list_t __list;
# define __PTHREAD_MUTEX_HAVE_PREV      1
# define __PTHREAD_SPINS             0, 0
#else
    unsigned int __nusers;
    __extension__ union
    {
      struct
      {
        short __espins;
        short __elision;
# define __spins __elision_data.__espins
# define __elision __elision_data.__elision
# define __PTHREAD_SPINS         { 0, 0 }
      } __elision_data;
      __pthread_slist_t __list;
    };
#endif

นี่คือโครงสร้างสำหรับชนิดข้อมูล mutex เช่น pthread_mutex_t เมื่อ mutex ถูกล็อค __ ล็อคตั้งค่าเป็น 1 เมื่อปลดล็อค __lock ตั้งค่าเป็น 0

สิ่งนี้ทำให้มั่นใจได้ว่าไม่มีกระบวนการ / เธรดสองกระบวนการใดที่สามารถเข้าถึงส่วนวิกฤติในเวลาเดียวกัน

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