mutex เป็นแนวคิดการเขียนโปรแกรมที่ใช้บ่อยในการแก้ปัญหาหลายเธรด คำถามของฉันต่อชุมชน:
Mutex คืออะไรและคุณใช้มันอย่างไร
mutex เป็นแนวคิดการเขียนโปรแกรมที่ใช้บ่อยในการแก้ปัญหาหลายเธรด คำถามของฉันต่อชุมชน:
Mutex คืออะไรและคุณใช้มันอย่างไร
คำตอบ:
เมื่อฉันมีการพูดคุยกันอย่างร้อนแรงในที่ทำงานฉันใช้ไก่ยางซึ่งฉันเก็บไว้ในโต๊ะของฉันในโอกาสเช่นนี้ คนที่ถือไก่เป็นคนเดียวที่ได้รับอนุญาตให้พูดคุย หากคุณไม่ถือไก่คุณไม่สามารถพูดได้ คุณสามารถระบุได้ว่าคุณต้องการไก่และรอจนกว่าคุณจะได้รับมันก่อนที่คุณจะพูด เมื่อคุณพูดเสร็จแล้วคุณสามารถส่งไก่กลับไปที่ผู้ดำเนินรายการซึ่งจะส่งให้คนต่อไปเพื่อพูด สิ่งนี้ทำให้มั่นใจได้ว่าผู้คนจะไม่พูดคุยกันและมีพื้นที่ของตนเองในการพูดคุย
แทนที่ Chicken ด้วย Mutex และบุคคลที่มี thread และโดยทั่วไปคุณมีแนวคิดของ mutex
แน่นอนไม่มีสิ่งเช่น mutex ยาง ไก่ยางเท่านั้น แมวของฉันเคยมีหนูยาง แต่พวกเขากินมัน
แน่นอนว่าก่อนที่คุณจะใช้ไก่ยางพาราคุณต้องถามตัวเองว่าคุณต้องการ 5 คนในห้องจริงหรือไม่และจะง่ายกว่าถ้ามีคนคนหนึ่งอยู่ในห้องด้วยตนเอง จริงๆแล้วนี่เป็นการขยายความคล้ายคลึงกัน แต่คุณจะได้ความคิด
Mutex เป็นแฟล็กที่ไม่เกิดร่วมกัน มันทำหน้าที่เป็นผู้รักษาประตูไปยังส่วนของรหัสที่อนุญาตให้หนึ่งเธรดในและปิดกั้นการเข้าถึงอื่น ๆ ทั้งหมด สิ่งนี้ทำให้มั่นใจได้ว่าโค้ดที่ถูกควบคุมจะถูกโจมตีด้วยเธรดครั้งละหนึ่งรายการเท่านั้น เพียงให้แน่ใจว่าจะปล่อย mutex เมื่อคุณทำเสร็จแล้ว :)
การยกเว้นซึ่งกันและกัน นี่คือรายการ Wikipedia ที่มัน:
http://en.wikipedia.org/wiki/Mutual_exclusion
จุดของ mutex คือการซิงโครไนซ์สองเธรด เมื่อคุณมีสองเธรดที่พยายามเข้าถึงรีซอร์สเดียวรูปแบบทั่วไปคือมีบล็อกแรกของรหัสที่พยายามเข้าถึงเพื่อตั้งค่า mutex ก่อนที่จะป้อนรหัส เมื่อบล็อกรหัสที่สองพยายามเข้าถึงจะเห็นการตั้งค่า mutex และรอจนกว่าบล็อกรหัสแรกจะเสร็จสมบูรณ์ (และยกเลิกการตั้งค่า mutex) จากนั้นดำเนินการต่อ
รายละเอียดเฉพาะของวิธีการที่จะประสบความสำเร็จอย่างเห็นได้ชัดนั้นแตกต่างกันอย่างมากตามภาษาการเขียนโปรแกรม
เมื่อคุณมีแอ็พพลิเคชันแบบมัลติเธรดบางครั้งเธรดที่แตกต่างกันจะแบ่งใช้รีซอร์สทั่วไปเช่นตัวแปรหรือคล้ายกัน แหล่งข้อมูลที่ใช้ร่วมกันนี้มักไม่สามารถเข้าถึงได้ในเวลาเดียวกันดังนั้นจึงจำเป็นต้องมีการสร้างเพื่อให้แน่ใจว่ามีเพียงหนึ่งเธรดเท่านั้นที่ใช้ทรัพยากรนั้นในแต่ละครั้ง
แนวคิดนี้เรียกว่า "การยกเว้นร่วมกัน" (Mutex แบบสั้น) และเป็นวิธีการตรวจสอบให้แน่ใจว่าอนุญาตให้มีเธรดเดียวเท่านั้นภายในพื้นที่นั้นโดยใช้ทรัพยากรนั้นเป็นต้น
วิธีใช้เป็นเฉพาะภาษา แต่มักจะ (ถ้าไม่เสมอ) ตามระบบปฏิบัติการ mutex
บางภาษาไม่ต้องการโครงสร้างนี้เนื่องจากกระบวนทัศน์ตัวอย่างเช่นการเขียนโปรแกรมใช้งานได้ (Haskell, ML เป็นตัวอย่างที่ดี)
ใน 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;
}
}
คำสั่งล็อคโดยใช้วัตถุล็อคส่วนตัวสร้างส่วนที่สำคัญ ต้องการให้แต่ละเธรดรอจนกว่าก่อนหน้านี้จะเสร็จสิ้น เธรดแรกจะเข้าสู่ส่วนและเริ่มต้นอินสแตนซ์ เธรดที่สองจะรอรับในส่วนและรับอินสแตนซ์ที่เตรียมใช้งาน
การซิงโครไนซ์ประเภทใด ๆ ของสมาชิกแบบสแตติกอาจใช้คำสั่งล็อคในทำนองเดียวกัน
คืออะไร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คืออะไร:
พิจารณาเดียวห้องน้ำมีที่สำคัญ เมื่อมีคนเข้าพวกเขาใช้เวลาที่สำคัญและห้องน้ำอยู่ในครอบครอง ถ้ามีคนอื่นที่จะตอบสนองความต้องการใช้ห้องน้ำที่พวกเขาจำเป็นต้องรอในคิว เมื่อบุคคลในห้องน้ำเสร็จแล้วพวกเขาจะส่งกุญแจไปยังบุคคลต่อไปในคิว เข้าท่าใช่ไหม?
แปลงห้องสุขาในเรื่องกับทรัพยากรที่ใช้ร่วมกันและที่สำคัญไปยังmutex การเอากุญแจไปเข้าห้องน้ำ (รับกุญแจ) อนุญาตให้คุณใช้กุญแจได้ หากไม่มีกุญแจ (ล็อคถูกล็อค) คุณต้องรอ เมื่อบุคคลนั้นส่งคืนกุญแจ ( ปลดล็อค ) คุณมีอิสระที่จะรับกุญแจได้ทันที
ในการทำความเข้าใจกับ MUTEX ในตอนแรกคุณต้องรู้ว่า "สภาพการแข่งขัน" คืออะไรและจากนั้นมีเพียงคุณเท่านั้นที่จะเข้าใจว่าทำไมจึงต้องมี MUTEX สมมติว่าคุณมีโปรแกรมหลายเธรดและคุณมีสองเธรด ตอนนี้คุณมีงานหนึ่งงานในคิวงาน เธรดแรกจะตรวจสอบคิวงานและหลังจากหางานมันจะเริ่มดำเนินการ เธรดที่สองจะตรวจสอบคิวงานและพบว่ามีหนึ่งงานในคิว ดังนั้นมันจะกำหนดตัวชี้งานเดียวกัน ดังนั้นตอนนี้จะเกิดอะไรขึ้นเธรดทั้งคู่กำลังดำเนินงานเดียวกัน สิ่งนี้จะทำให้เกิดการแบ่งกลุ่มผิดพลาด นี่คือตัวอย่างของสภาพการแข่งขัน
การแก้ไขปัญหานี้คือ MUTEX MUTEX เป็นล็อคชนิดหนึ่งที่ล็อคทีละหนึ่งเธรด หากเธรดอื่นต้องการล็อคเธรดก็จะถูกบล็อก
Mutexes มีประโยชน์ในสถานการณ์ที่คุณจำเป็นต้องบังคับใช้การเข้าถึงแบบเอกสิทธิ์เฉพาะบุคคลไปยังทรัพยากรที่มีหลายกระบวนการซึ่งการล็อกปกติจะไม่ช่วยได้เนื่องจากจะใช้งานได้เฉพาะกับเธรดที่ตรงกันเท่านั้น
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
สิ่งนี้ทำให้มั่นใจได้ว่าไม่มีกระบวนการ / เธรดสองกระบวนการใดที่สามารถเข้าถึงส่วนวิกฤติในเวลาเดียวกัน