ตัวอย่าง / กวดวิชา Mutex? [ปิด]


176

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

หนึ่งในไวยากรณ์ที่ไม่เข้าใจง่ายของ mutex คือpthread_mutex_lock( &mutex1 );มันดูเหมือนว่า mutex กำลังถูกล็อคเมื่อสิ่งที่ฉันต้องการล็อคจริงๆคือตัวแปรอื่น ๆ ไวยากรณ์นี้หมายความว่าการล็อก mutex ล็อคขอบเขตของรหัสจนกว่า mutex จะถูกปลดล็อกหรือไม่? จากนั้นเธรดจะรู้ได้อย่างไรว่าพื้นที่ถูกล็อก [ อัพเดท: กระทู้รู้ว่าพื้นที่ถูกล็อคโดยการ ฟันดาบของหน่วยความจำ ] และปรากฏการณ์เช่นนี้ไม่ควรถูกเรียกว่าส่วนวิกฤต [ ปรับปรุง: วัตถุส่วนที่สำคัญมีอยู่ใน Windows เท่านั้นโดยที่วัตถุนั้นเร็วกว่า mutexes และสามารถมองเห็นได้เฉพาะเธรดที่ใช้งานเท่านั้น มิฉะนั้นส่วนสำคัญจะอ้างถึงพื้นที่ของรหัสที่ป้องกันโดย mutex ]

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


2
ดำเนินการต่อเพื่อเน้นความต้องการการสอนแบบง่าย ๆ (ไม่ว่าจะเป็นการเพิ่มเธรด, tbb หรือ pthreads): ตัวอย่างของความสับสน: 1. stackoverflow.com/questions/3528877/… 2. stackoverflow.com/questions/2979525/… 3 stackoverflow.com/questions/2095977/to-mutex-or-not-to-mutex 4. stackoverflow.com/questions/3931026/… 5. stackoverflow.com/questions/1525189/…
Nav

1
ฉันไม่ได้หมายถึงสิ่งนี้อย่างก้าวร้าว แต่ความคิดเห็นล่าสุดของคุณแสดงให้ฉันเห็นว่าเราต้องการการเปรียบเทียบที่น้อยกว่าและคำอธิบายทางเทคนิคที่ดีขึ้นเกี่ยวกับวิธีที่ mutex ทำงานได้และทำไมเราถึงต้องการพวกเขา
San Jacinto

@San: ไม่มีความผิด :) ความคิดเห็นของฉันมีความหมายเพียงเพื่อแนะนำว่ามือใหม่จะได้คำอธิบายสั้น ๆ ที่ชัดเจนที่สุดของ mutexes การเปรียบเทียบหลายครั้งอาจทำให้เกิดความสับสนสำหรับมือใหม่ดังนั้นการเปรียบเทียบที่แตกต่างกันจึงควรแยกไว้ต่างหาก เหตุผลทั้งหมดที่ฉันโพสต์คำถามและคำตอบก็เพราะในฐานะที่เป็นมือใหม่ฉันพบว่ามันเจ็บปวดที่จะอ่านคำอธิบายที่ยาวและตัวอย่างโค้ด ฉันไม่ต้องการให้คนอื่นผ่านความเจ็บปวด
Nav

2
@Cory: หากสามารถปรับปรุงคำตอบนี้ได้ฉันยินดีที่จะรับข้อเสนอแนะของคุณ ฉันแค่ดีใจที่คนอื่น ๆ จำนวนมากพบว่ามันมีประโยชน์ ถ้ามันไม่ช่วยคุณก็มีคำตอบจากคนอื่นเช่นกันที่ชี้ไปที่บทช่วยสอน mutex อื่น ๆ ทำไมต้องเป็นลบ
Nav

คำตอบ:


278

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

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

ด้ายคือแต่ละคนmutexคือประตูจัดการล็อคคือมือของบุคคลทรัพยากรคือโทรศัพท์


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

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

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

ด้วยเธรด C ++ 11:

#include <iostream>
#include <thread>
#include <mutex>

std::mutex m;//you can use std::lock_guard if you want to be exception safe
int i = 0;

void makeACallFromPhoneBooth() 
{
    m.lock();//man gets a hold of the phone booth door and locks it. The other men wait outside
      //man happily talks to his wife from now....
      std::cout << i << " Hello Wife" << std::endl;
      i++;//no other thread can access variable i until m.unlock() is called
      //...until now, with no interruption from other men
    m.unlock();//man lets go of the door handle and unlocks the door
}

int main() 
{
    //This is the main crowd of people uninterested in making a phone call

    //man1 leaves the crowd to go to the phone booth
    std::thread man1(makeACallFromPhoneBooth);
    //Although man2 appears to start second, there's a good chance he might
    //reach the phone booth before man1
    std::thread man2(makeACallFromPhoneBooth);
    //And hey, man3 also joined the race to the booth
    std::thread man3(makeACallFromPhoneBooth);

    man1.join();//man1 finished his phone call and joins the crowd
    man2.join();//man2 finished his phone call and joins the crowd
    man3.join();//man3 finished his phone call and joins the crowd
    return 0;
}

รวบรวมและเรียกใช้โดยใช้ g++ -std=c++0x -pthread -o thread thread.cpp;./thread

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


2
@San: ฉันจะซื่อสัตย์ ใช่ฉันชอบความจริงที่ว่าคุณพยายามอย่างดีที่สุดเพื่ออธิบายรายละเอียด (กับโฟลว์) ให้กับมือใหม่ แต่ (โปรดอย่าเข้าใจผิดฉัน) ความตั้งใจของโพสต์นี้คือการวางแนวคิดในคำอธิบายสั้น ๆ (เพราะคำตอบอื่น ๆ ชี้ไปที่แบบฝึกหัดยาว) ฉันหวังว่าคุณจะไม่รังเกียจถ้าฉันขอให้คุณคัดลอกคำตอบทั้งหมดและโพสต์เป็นคำตอบแยกต่างหาก เพื่อให้ฉันสามารถย้อนกลับและแก้ไขคำตอบของฉันเพื่อชี้ไปที่คำตอบของคุณ
Nav

2
@Tom ในกรณีนั้นคุณไม่ควรเข้าถึง mutex นั้น การดำเนินการเกี่ยวกับมันควรได้รับการห่อหุ้มเพื่อให้สิ่งที่มันได้รับการปกป้องได้รับการปกป้องจากโรงเก็บอาวุธเช่นนั้น หากเมื่อคุณใช้ API ที่เปิดเผยของไลบรารีไลบรารีจะรับประกันว่าปลอดภัยต่อเธรดคุณจะปลอดภัยที่จะรวม mutex ที่แตกต่างกันอย่างชัดเจนเพื่อปกป้องรายการที่คุณแบ่งปัน มิฉะนั้นคุณกำลังเพิ่มมือจับประตูใหม่ตามที่คุณแนะนำ
San Jacinto

2
หากต้องการขยายจุดของฉันสิ่งที่คุณต้องการทำคือเพิ่มอีกห้องที่ใหญ่ขึ้นรอบ ๆ บูธ ห้องอาจมีห้องน้ำและฝักบัว สมมติว่ามีเพียง 1 คนเท่านั้นที่ได้รับอนุญาตในห้องพักพร้อมกัน คุณต้องออกแบบห้องเพื่อให้ห้องนี้ควรมีประตูที่มีมือจับที่ป้องกันการเข้าห้องเหมือนตู้โทรศัพท์ ดังนั้นตอนนี้แม้ว่าคุณจะมี mutex พิเศษคุณสามารถนำตู้โทรศัพท์มาใช้ใหม่ในโครงการใดก็ได้ อีกทางเลือกหนึ่งคือการเปิดเผยกลไกการล็อคสำหรับอุปกรณ์แต่ละชิ้นในห้องและจัดการล็อคในระดับห้อง ไม่ว่าด้วยวิธีใดคุณจะไม่เพิ่มการล็อคใหม่ไปยังวัตถุเดียวกัน
San Jacinto

8
ตัวอย่างเช่น C ++ 11 เธรดของคุณเป็นสิ่งที่ผิด เพื่อให้เป็น TBB หนึ่งเงื่อนงำที่อยู่ในชื่อขอบเขตล็อค
Jonathan Wakely

3
ฉันตระหนักดีถึงทั้ง @Jonathan (could've shown scoped locking by not using acquire and release - which also is exception safe -, but this is clearerคุณดูเหมือนจะไม่ได้รับประโยคที่ผมเขียน สำหรับการใช้การล็อคแบบกำหนดขอบเขตนั้นขึ้นอยู่กับผู้พัฒนาขึ้นอยู่กับประเภทของแอปพลิเคชันที่พวกเขากำลังสร้าง คำตอบนี้มีจุดประสงค์เพื่อกล่าวถึงความเข้าใจพื้นฐานของแนวคิด mutex และไม่ให้เข้ากับความซับซ้อนทั้งหมดของมันดังนั้นความคิดเห็นและลิงก์ของคุณยินดีต้อนรับ แต่ไม่ได้อยู่ในขอบเขตของบทช่วยสอนนี้
Nav

41

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

//somewhere long ago, we have i declared as int
void my_concurrently_called_function()
{
  i++;
}

ฟังก์ชั่นภายในของฟังก์ชั่นนี้ดูเรียบง่าย มันเป็นเพียงคำสั่งเดียว อย่างไรก็ตามการเทียบเท่าภาษาเทียมประกอบโดยทั่วไปอาจเป็น:

load i from memory into a register
add 1 to i
store i back into memory

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

thread 1 load 0 into register from memory corresponding to i //register is currently 0
thread 1 add 1 to a register //register is now 1, but not memory is 0
thread 2 load 0 into register from memory corresponding to i
thread 2 add 1 to a register //register is now 1, but not memory is 0
thread 1 write register to memory //memory is now 1
thread 2 write register to memory //memory is now 1

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

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

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

เมื่อเธรดดำเนินการส่วนที่สำคัญแล้วควรปล่อยการล็อกบน mutex เพื่อให้เธรดอื่นสามารถรับการล็อกบน mutex

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

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

ในทางเทคนิคแล้วเราต้องการการสนับสนุนด้านฮาร์ดแวร์เพื่อช่วยเหลือเรา นักออกแบบฮาร์ดแวร์ให้คำแนะนำเครื่องที่ทำมากกว่าหนึ่งสิ่ง แต่รับประกันเป็นอะตอม ตัวอย่างคลาสสิกของคำสั่งดังกล่าวคือชุดการทดสอบและชุด (TAS) เมื่อพยายามรับการล็อคทรัพยากรเราอาจใช้ TAS อาจตรวจสอบเพื่อดูว่าค่าในหน่วยความจำเท่ากับ 0 หรือไม่หากเป็นเช่นนั้นก็จะเป็นสัญญาณของเราว่าทรัพยากรนั้นกำลังใช้งานอยู่และเราไม่ได้ทำอะไรเลย เรารอด้วยกลไกบางอย่าง pthreads mutex จะทำให้เราเข้าสู่คิวพิเศษในระบบปฏิบัติการและจะแจ้งให้เราทราบเมื่อมีทรัพยากรพร้อมใช้งานระบบ Dumber อาจทำให้เราต้องวนรอบการปั่นที่แน่นหนา . หากค่าในหน่วยความจำไม่ใช่ 0 TAS จะตั้งค่าตำแหน่งเป็นค่าอื่นที่ไม่ใช่ 0 โดยไม่ต้องใช้คำสั่งอื่น มัน' เหมือนการรวมคำสั่งสองชุดเข้าด้วยกันเป็น 1 เพื่อให้อะตอมมิกซิตี้ของเรา ดังนั้นการทดสอบและการเปลี่ยนแปลงค่า (หากมีการเปลี่ยนแปลงที่เหมาะสม) ไม่สามารถถูกขัดจังหวะเมื่อเริ่มต้นขึ้น เราสามารถสร้าง mutex ได้บนคำสั่งดังกล่าว

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


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

13

หัวข้อการสอนที่ดีที่สุดที่ฉันรู้จักอยู่ที่นี่:

https://computing.llnl.gov/tutorials/pthreads/

ฉันชอบที่มันเขียนเกี่ยวกับ API ไม่ใช่เกี่ยวกับการใช้งานเฉพาะและมันให้ตัวอย่างง่ายๆที่ดีเพื่อช่วยให้คุณเข้าใจการซิงโครไนซ์


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

7

ฉันสะดุดกับโพสต์นี้เมื่อเร็ว ๆ นี้และคิดว่ามันต้องการโซลูชันที่อัปเดตสำหรับ c ++ 11 mutex ของไลบรารีมาตรฐาน (เช่น std :: mutex)

ฉันได้วางโค้ดด้านล่าง (ขั้นตอนแรกของฉันกับ mutex - ฉันเรียนรู้การทำงานพร้อมกันใน win32 ด้วย HANDLE, SetEvent, WaitForMultipleObjects ฯลฯ )

เนื่องจากเป็นความพยายามครั้งแรกของฉันกับ std :: mutex และเพื่อน ๆ ฉันชอบที่จะเห็นความคิดเห็นคำแนะนำและการปรับปรุง!

#include <condition_variable>
#include <mutex>
#include <algorithm>
#include <thread>
#include <queue>
#include <chrono>
#include <iostream>


int _tmain(int argc, _TCHAR* argv[])
{   
    // these vars are shared among the following threads
    std::queue<unsigned int>    nNumbers;

    std::mutex                  mtxQueue;
    std::condition_variable     cvQueue;
    bool                        m_bQueueLocked = false;

    std::mutex                  mtxQuit;
    std::condition_variable     cvQuit;
    bool                        m_bQuit = false;


    std::thread thrQuit(
        [&]()
        {
            using namespace std;            

            this_thread::sleep_for(chrono::seconds(5));

            // set event by setting the bool variable to true
            // then notifying via the condition variable
            m_bQuit = true;
            cvQuit.notify_all();
        }
    );


    std::thread thrProducer(
        [&]()
        {
            using namespace std;

            int nNum = 13;
            unique_lock<mutex> lock( mtxQuit );

            while ( ! m_bQuit )
            {
                while( cvQuit.wait_for( lock, chrono::milliseconds(75) ) == cv_status::timeout )
                {
                    nNum = nNum + 13 / 2;

                    unique_lock<mutex> qLock(mtxQueue);
                    cout << "Produced: " << nNum << "\n";
                    nNumbers.push( nNum );
                }
            }
        }   
    );

    std::thread thrConsumer(
        [&]()
        {
            using namespace std;
            unique_lock<mutex> lock(mtxQuit);

            while( cvQuit.wait_for(lock, chrono::milliseconds(150)) == cv_status::timeout )
            {
                unique_lock<mutex> qLock(mtxQueue);
                if( nNumbers.size() > 0 )
                {
                    cout << "Consumed: " << nNumbers.front() << "\n";
                    nNumbers.pop();
                }               
            }
        }
    );

    thrQuit.join();
    thrProducer.join();
    thrConsumer.join();

    return 0;
}

1
Super! ขอบคุณสำหรับการโพสต์ แม้ว่าที่ฉันได้กล่าวถึงก่อนหน้านี้วัตถุประสงค์ของฉันเพียงเพื่ออธิบายแนวคิดของ mutex บทเรียนอื่น ๆ ทั้งหมดทำให้มันยากมากด้วยแนวคิดเพิ่มเติมของผู้บริโภคผู้ผลิตและตัวแปรเงื่อนไข ฯลฯ ซึ่งทำให้ยากมากสำหรับฉันที่จะเข้าใจสิ่งที่เกิดขึ้นบนโลก
Nav

4

ฟังก์ชันpthread_mutex_lock()จะรับ mutex สำหรับการเรียกเธรดหรือบล็อกเธรดจนกว่าจะสามารถรับ mutex ได้ ที่เกี่ยวข้องpthread_mutex_unlock()ปล่อย mutex

คิดว่า mutex เป็นคิว ทุกเธรดที่พยายามรับ mutex จะถูกวางไว้ที่ท้ายคิว เมื่อเธรดออก mutex เธรดถัดไปในคิวจะดับและกำลังทำงาน

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


1
มันรับประกันได้หรือไม่ว่าการพยายามครั้งต่อไปที่จะเข้ามา?
Arsen Mkrtchyan

1
@Arsen ไม่มีการรับประกัน มันเป็นเพียงการเปรียบเทียบที่เป็นประโยชน์
chrisaycock

3

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

Mutex เป็นเพียงเซมาฟอร์ที่ง่าย หากคุณอ่านเกี่ยวกับพวกเขาและเข้าใจพวกเขาคุณเข้าใจ mutexes มีคำถามหลายข้อเกี่ยวกับ mutexes และ semaphores ใน SO ความแตกต่างระหว่างสัญญาณไบนารีและ mutex , เมื่อเราควรใช้ mutex และเมื่อเราควรใช้สัญญาณและอื่น ๆ ตัวอย่างห้องน้ำในลิงค์แรกเป็นตัวอย่างที่ดีอย่างที่คิด รหัสทั้งหมดใช้เพื่อตรวจสอบว่ามีรหัสหรือไม่และขอสงวนรหัสไว้ โปรดสังเกตว่าคุณไม่ได้จองห้องน้ำจริงๆ แต่เป็นกุญแจ


1
pthread_mutex_lockไม่สามารถกลับมาได้ถ้ามีคนอื่นถือกุญแจไว้ มันบล็อกในกรณีนี้และนั่นคือจุดรวม pthread_mutex_trylockเป็นฟังก์ชั่นที่จะกลับมาหากล็อคอยู่
. GitHub หยุดช่วยน้ำแข็ง

1
ใช่ฉันไม่ได้ตระหนักในตอนแรกว่าการดำเนินการนี้คืออะไร
Makis


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