เมื่อใดที่เราควรใช้ mutex และเมื่อใดที่เราควรใช้ semaphore?
เมื่อใดที่เราควรใช้ mutex และเมื่อใดที่เราควรใช้ semaphore?
คำตอบ:
นี่คือวิธีที่ฉันจำได้ว่าเมื่อใดควรใช้อะไร -
สัญญาณ: ใช้สัญญาณเมื่อคุณ (ด้าย) ต้องการนอนหลับจนกว่าเธรดอื่นจะบอกให้คุณตื่น สัญญาณ 'ลง' เกิดขึ้นในเธรดเดียว (ผู้ผลิต) และสัญญาณ 'ขึ้น' (สำหรับเซมาฟอร์เดียวกัน) เกิดขึ้นในเธรดอื่น (ผู้บริโภค) เช่น: ในปัญหาผู้ผลิต - ผู้บริโภคผู้ผลิตต้องการนอนหลับจนกว่าช่องบัฟเฟอร์อย่างน้อยหนึ่งช่องว่าง - เท่านั้น เธรดผู้บริโภคสามารถบอกได้เมื่อช่องบัฟเฟอร์ว่างเปล่า
Mutex: ใช้ mutex เมื่อคุณ (เธรด) ต้องการรันโค้ดที่ไม่ควรดำเนินการโดยเธรดอื่นในเวลาเดียวกัน Mutex 'down' เกิดขึ้นในเธรดเดียวและ mutex 'up' จะต้องเกิดขึ้นในเธรดเดียวกันในภายหลัง เช่น: หากคุณกำลังลบโหนดจากรายการที่เชื่อมโยงส่วนกลางคุณไม่ต้องการให้เธรดอื่นยุ่งเกี่ยวกับพอยน์เตอร์ในขณะที่คุณกำลังลบโหนด เมื่อคุณได้รับ mutex และกำลังยุ่งอยู่กับการลบโหนดหากเธรดอื่นพยายามรับ mutex เดียวกันมันจะเข้าสู่โหมดสลีปจนกว่าคุณจะปล่อย mutex
Spinlock: ใช้Spinlockเมื่อคุณต้องการใช้ mutex จริงๆ แต่เธรดของคุณไม่ได้รับอนุญาตให้เข้าสู่โหมดสลีป เช่น: ตัวจัดการการขัดจังหวะภายในเคอร์เนล OS จะต้องไม่อยู่ในโหมดสลีป หากเป็นเช่นนั้นระบบจะหยุดทำงาน / ขัดข้อง หากคุณต้องการแทรกโหนดไปยังรายการที่เชื่อมโยงร่วมกันทั่วโลกจากตัวจัดการขัดจังหวะให้รับ spinlock - insert node - release spinlock
mutex เป็นออบเจ็กต์การยกเว้นซึ่งกันและกันคล้ายกับเซมาฟอร์ แต่อนุญาตให้ล็อกเกอร์ได้ครั้งละหนึ่งรายการเท่านั้นและข้อ จำกัด ในการเป็นเจ้าของอาจเข้มงวดกว่าเซมาฟอร์
สามารถคิดได้ว่าเทียบเท่ากับเซมาฟอร์การนับปกติ (โดยมีการนับหนึ่ง) และข้อกำหนดที่สามารถปล่อยได้โดยเธรดเดียวกับที่ล็อกไว้เท่านั้น(a) (ก)
ในทางกลับกันสัญญาณมีการนับโดยพลการและสามารถล็อคได้โดยตู้เก็บของจำนวนมากพร้อมกัน และอาจไม่มีข้อกำหนดว่าจะเผยแพร่โดยเธรดเดียวกับที่อ้างสิทธิ์ (แต่ถ้าไม่คุณต้องติดตามอย่างรอบคอบว่าใครมีหน้าที่รับผิดชอบในขณะนี้เหมือนกับหน่วยความจำที่จัดสรร)
ดังนั้นหากคุณมีอินสแตนซ์ของทรัพยากรจำนวนหนึ่ง (เช่นเทปไดรฟ์สามตัว) คุณสามารถใช้เซมาฟอร์ที่มีจำนวน 3 ได้โปรดทราบว่าสิ่งนี้ไม่ได้บอกคุณว่าคุณมีเทปไดร์ฟใดที่คุณมี จำนวนหนึ่ง
นอกจากนี้ด้วย semaphores ยังเป็นไปได้ที่ล็อกเกอร์เดียวจะล็อกหลายอินสแตนซ์ของทรัพยากรเช่นสำหรับการคัดลอกแบบเทปต่อเทป หากคุณมีทรัพยากรเดียว (พูดตำแหน่งหน่วยความจำที่คุณไม่ต้องการทำให้เสียหาย) mutex จะเหมาะสมกว่า
การดำเนินการที่เทียบเท่าคือ:
Counting semaphore Mutual exclusion semaphore
-------------------------- --------------------------
Claim/decrease (P) Lock
Release/increase (V) Unlock
นอกเหนือจาก:ในกรณีที่คุณเคยสงสัยเกี่ยวกับตัวอักษรแปลก ๆ ที่ใช้สำหรับการอ้างสิทธิ์และการปล่อยสัญญาณเนื่องจากผู้ประดิษฐ์เป็นชาวดัตช์ Probeer te verlagen หมายถึงการพยายามและลดในขณะที่ verhogen หมายถึงการเพิ่มขึ้น
(ก) ... หรืออาจคิดได้ว่าเป็นสิ่งที่แตกต่างอย่างสิ้นเชิงจากสัญญาณซึ่งอาจปลอดภัยกว่าเนื่องจากการใช้งานที่แตกต่างกันเกือบตลอดเวลา
เป็นสิ่งสำคัญมากที่ต้องเข้าใจว่า mutex ไม่ใช่เซมาฟอร์ที่มีการนับ 1!
นี่คือเหตุผลที่มีสิ่งต่างๆเช่นเซมาโฟเรสไบนารี (ซึ่งเป็นเซมาโฟเรสที่มีการนับ 1 จริงๆ)
ความแตกต่างระหว่าง Mutex และ Binary-Semaphore คือหลักการของความเป็นเจ้าของ:
mutex ได้มาจากงานดังนั้นจึงต้องถูกปลดโดยภารกิจเดียวกัน สิ่งนี้ทำให้สามารถแก้ไขปัญหาต่างๆเกี่ยวกับเซมาโฟร์แบบไบนารีได้ (การรีลีสโดยบังเอิญการหยุดชะงักซ้ำและการผกผันลำดับความสำคัญ)
Caveat: ฉันเขียนว่า "ทำให้เป็นไปได้" หากและวิธีการแก้ไขปัญหาเหล่านี้ขึ้นอยู่กับการใช้งานระบบปฏิบัติการ
เนื่องจากต้องปล่อย mutex โดยงานเดียวกันจึงไม่ดีมากสำหรับการซิงโครไนซ์งาน แต่ถ้ารวมกับตัวแปรเงื่อนไขคุณจะได้หน่วยการสร้างที่ทรงพลังมากสำหรับการสร้าง ipc primitives ทุกชนิด
ดังนั้นคำแนะนำของฉันคือ: หากคุณมีการนำ mutexes และตัวแปรเงื่อนไขมาใช้อย่างหมดจด (เช่นกับ POSIX pthreads) ให้ใช้สิ่งเหล่านี้
ใช้ semaphores เฉพาะในกรณีที่เหมาะสมกับปัญหาที่คุณกำลังพยายามแก้ไขอย่าพยายามสร้างแบบดั้งเดิมอื่น ๆ (เช่น rw-locks ออกจาก semaphores ใช้ mutexes และตัวแปรเงื่อนไขสำหรับสิ่งเหล่านี้)
มี mutexes และ semaphores ที่เข้าใจผิดมากมาย คำอธิบายที่ดีที่สุดที่ฉันพบในบทความ 3 ตอนนี้:
Mutex กับ Semaphores - ตอนที่ 1: Semaphores
Mutex กับ Semaphores - ตอนที่ 2: The Mutex
Mutex กับ Semaphores - ส่วนที่ 3 (ส่วนสุดท้าย): ปัญหาการกีดกันซึ่งกันและกัน
ในขณะที่คำตอบของ @opaxdiablo นั้นถูกต้องทั้งหมดฉันต้องการชี้ให้เห็นว่าสถานการณ์การใช้งานของทั้งสองสิ่งนั้นแตกต่างกันมาก mutex ใช้สำหรับป้องกันส่วนต่างๆของโค้ดไม่ให้ทำงานพร้อมกันโดยใช้ semaphores สำหรับเธรดหนึ่งเพื่อส่งสัญญาณให้เธรดอื่นทำงาน
/* Task 1 */
pthread_mutex_lock(mutex_thing);
// Safely use shared resource
pthread_mutex_unlock(mutex_thing);
/* Task 2 */
pthread_mutex_lock(mutex_thing);
// Safely use shared resource
pthread_mutex_unlock(mutex_thing); // unlock mutex
สถานการณ์สัญญาณแตกต่างกัน:
/* Task 1 - Producer */
sema_post(&sem); // Send the signal
/* Task 2 - Consumer */
sema_wait(&sem); // Wait for signal
ดูhttp://www.netrino.com/node/202สำหรับคำอธิบายเพิ่มเติม
sema_wait
:-) ในความคิดของฉันทั้งสองอย่างเกี่ยวกับทรัพยากรและการแจ้งเตือนที่ส่งไปยังเธรดอื่น ๆ นั้นเป็นผลข้างเคียง (สำคัญมากและมีประสิทธิภาพ) ของ การป้องกัน.
You say that the usage pattern of semaphores is to notify threads
ประเด็นหนึ่งเกี่ยวกับการแจ้งกระทู้ คุณสามารถโทรsem_post
จากเครื่องจัดการสัญญาณได้อย่างปลอดภัย ( pubs.opengroup.org/onlinepubs/009695399/functions/… ) แต่ไม่แนะนำให้โทรpthread_mutex_lock
และpthread_mutex_unlock
จากตัวจัดการสัญญาณ ( manpages.ubuntu.com/manpages/lucid/man3/… )
ดู "ตัวอย่างห้องน้ำ" - http://pheatt.emporia.edu/courses/2010/cs557f10/hand07/Mutex%20vs_%20Semaphore.htm :
Mutex:
เป็นกุญแจสำคัญในการเข้าห้องน้ำ บุคคลหนึ่งสามารถมีกุญแจ - ครอบครองห้องน้ำ - ในเวลานั้น เมื่อเสร็จแล้วบุคคลนั้นจะให้ (ปลดปล่อย) คีย์ให้กับบุคคลถัดไปในคิว
อย่างเป็นทางการ: "โดยทั่วไปแล้ว Mutexes จะใช้เพื่อกำหนดลำดับการเข้าถึงส่วนของโค้ด re-entrant ที่ไม่สามารถดำเนินการพร้อมกันได้มากกว่าหนึ่งเธรดอ็อบเจ็กต์ mutex อนุญาตให้เธรดหนึ่งเธรดเข้าไปในส่วนที่ควบคุมได้เท่านั้นโดยบังคับให้เธรดอื่นที่พยายามเข้าถึง ส่วนนั้นให้รอจนกว่าเธรดแรกจะออกจากส่วนนั้น " อ้างอิง: Symbian Developer Library
(mutex เป็นเซมาฟอร์ที่มีค่า 1)
สัญญาณ:
คือจำนวนกุญแจห้องน้ำที่เหมือนกันฟรี ตัวอย่างเช่นสมมติว่าเรามีห้องสุขาสี่ห้องที่มีกุญแจและกุญแจเหมือนกัน จำนวนเซมาฟอร์ - จำนวนคีย์ - ถูกตั้งค่าเป็น 4 เมื่อเริ่มต้น (ห้องน้ำทั้งสี่ห้องไม่มีค่าใช้จ่าย) จากนั้นค่าการนับจะลดลงเมื่อมีคนเข้ามาหากห้องสุขาทั้งหมดเต็มเช่น ไม่มีคีย์ว่างเหลืออยู่จำนวนเซมาฟอร์คือ 0 ตอนนี้เมื่อ eq คนหนึ่งออกจากห้องน้ำสัญญาณเพิ่มขึ้นเป็น 1 (คีย์ฟรีหนึ่งอัน) และมอบให้กับคนถัดไปในคิว
อย่างเป็นทางการ: "เซมาฟอร์ จำกัด จำนวนผู้ใช้พร้อมกันของทรัพยากรที่ใช้ร่วมกันไม่เกินจำนวนสูงสุดเธรดสามารถร้องขอการเข้าถึงทรัพยากร (การลดลงของสัญญาณ) และสามารถส่งสัญญาณว่าพวกเขาใช้ทรัพยากรเสร็จสิ้น " อ้างอิง: Symbian Developer Library
พยายามที่จะไม่ฟังดูตลก แต่ก็ช่วยตัวเองไม่ได้
คำถามของคุณควรเป็นอะไรคือความแตกต่างระหว่าง mutex และ semaphores? และเพื่อให้เป็นคำถามที่แม่นยำยิ่งขึ้นควรเป็น 'อะไรคือความสัมพันธ์ระหว่าง mutex และ semaphores?'
(ฉันจะเพิ่มคำถามนั้น แต่ฉันมั่นใจร้อย% ว่าโมเดอเรเตอร์ที่ขี้อิจฉาบางคนจะปิดมันเป็นซ้ำโดยไม่เข้าใจความแตกต่างระหว่างความแตกต่างและความสัมพันธ์)
ในคำศัพท์เกี่ยวกับวัตถุเราสามารถสังเกตได้ว่า:
การสังเกต 1 Semaphore มี mutex
ข้อสังเกต 2 Mutex ไม่ใช่สัญญาณและสัญญาณไม่ใช่ mutex
มีเซมาโฟร์บางตัวที่จะทำหน้าที่ราวกับว่ามันเป็น mutex เรียกว่าเซมาโฟร์ไบนารี แต่พวกมันไม่ได้เป็นแบบไม่ปิดเสียง
มีส่วนผสมพิเศษที่เรียกว่า Signaling (posix ใช้ condition_variable สำหรับชื่อนั้น) ซึ่งจำเป็นในการสร้าง Semaphore จาก mutex คิดว่าเป็นแหล่งที่มาของการแจ้งเตือน หากสองเธรดหรือมากกว่านั้นสมัครรับข้อมูลจากแหล่งการแจ้งเตือนเดียวกันก็เป็นไปได้ที่จะส่งข้อความไปยัง ONE หรือทั้งหมดเพื่อปลุกระบบ
อาจมีตัวนับตั้งแต่หนึ่งตัวขึ้นไปที่เกี่ยวข้องกับเซมาโฟร์ซึ่งได้รับการปกป้องโดย mutex สถานการณ์ที่เรียบง่ายที่สุดสำหรับเซมาฟอร์มีตัวนับเดียวซึ่งอาจเป็น 0 หรือ 1
นี่คือจุดที่ความสับสนหลั่งไหลเข้ามาราวกับฝนมรสุม
สัญญาณที่มีตัวนับที่สามารถเป็น 0 หรือ 1 ไม่ได้เป็น mutex
Mutex มีสองสถานะ (0,1) และหนึ่งความเป็นเจ้าของ (งาน) Semaphore มี mutex ตัวนับบางตัวและตัวแปรเงื่อนไข
ตอนนี้ใช้จินตนาการของคุณและการรวมกันของการใช้ตัวนับและเวลาที่จะส่งสัญญาณสามารถทำให้เกิดสัญญาณชนิดหนึ่งได้
ตัวนับเดี่ยวที่มีค่า 0 หรือ 1 และการส่งสัญญาณเมื่อค่าไปที่ 1 และจากนั้นปลดล็อกหนึ่งในผู้ชายที่รอสัญญาณ == สัญญาณไบนารี
ตัวนับเดี่ยวที่มีค่า 0 ถึง N และการส่งสัญญาณเมื่อค่าไปน้อยกว่า N และล็อก / รอเมื่อค่าเป็น N == การนับเซมาฟอร์
ตัวนับเดี่ยวที่มีค่า 0 ถึง N และส่งสัญญาณเมื่อค่าไปที่ N และล็อก / รอเมื่อค่าน้อยกว่า N == Barrier semaphore (ถ้าพวกเขาไม่เรียกมันก็ควรจะ)
ตอนนี้คำถามของคุณเมื่อจะใช้อะไร (หรือค่อนข้างถูกต้องรุ่นคำถาม 3 เมื่อใดควรใช้ mutex และเมื่อใดควรใช้ binary-semaphore เนื่องจากไม่มีการเปรียบเทียบกับ non-binary-semaphore) ใช้ mutex เมื่อ 1. คุณต้องการพฤติกรรมที่กำหนดเองซึ่งไม่ได้จัดทำโดย binary สัญญาณเช่นล็อคหมุนหรือล็อคเร็วหรือล็อคแบบวนซ้ำ โดยปกติคุณสามารถปรับแต่ง mutexes ด้วยแอตทริบิวต์ได้ แต่การปรับแต่ง semaphore นั้นไม่มีประโยชน์อะไรนอกจากการเขียน semaphore ใหม่ 2. คุณต้องการแบบดั้งเดิมที่มีน้ำหนักเบาหรือเร็วกว่า
ใช้ semaphores เมื่อสิ่งที่คุณต้องการมีให้อย่างแน่นอน
หากคุณไม่เข้าใจว่าอะไรคือสิ่งที่ได้รับจากการใช้งานไบนารี - เซมาฟอร์ของคุณดังนั้น IMHO ให้ใช้ mutex
และสุดท้ายอ่านหนังสือแทนที่จะพึ่ง SO
ฉันคิดว่าคำถามควรเป็นความแตกต่างระหว่าง mutex และ binary semaphore
Mutex = เป็นกลไกการล็อกการเป็นเจ้าของเฉพาะเธรดที่ได้รับการล็อกเท่านั้นที่สามารถคลายล็อกได้
binary Semaphore = เป็นกลไกสัญญาณมากกว่าเธรดที่มีลำดับความสำคัญสูงกว่าอื่น ๆ หากต้องการสามารถส่งสัญญาณและทำการล็อกได้
Mutex คือการปกป้องทรัพยากรที่ใช้ร่วมกัน
สัญญาณคือการส่งเธรด
Mutex:
นึกว่ามีตั๋วขาย เราสามารถจำลองกรณีที่มีคนจำนวนมากซื้อตั๋วในเวลาเดียวกัน: แต่ละคนเป็นด้ายเพื่อซื้อตั๋ว เห็นได้ชัดว่าเราจำเป็นต้องใช้ mutex เพื่อปกป้องตั๋วเนื่องจากเป็นทรัพยากรที่ใช้ร่วมกัน
สัญญาณ:
ลองนึกภาพว่าเราต้องทำการคำนวณดังต่อไปนี้:
c = a + b;
นอกจากนี้เรายังต้องการฟังก์ชั่นgeta()
การคำนวณa
, ฟังก์ชั่นgetb()
ในการคำนวณb
และฟังก์ชั่นที่จะทำการคำนวณgetc()
c = a + b
เห็นได้ชัดว่าเราไม่สามารถทำการc = a + b
เว้นเสียgeta()
และgetb()
ได้ดำเนินการเสร็จสิ้นแล้ว
หากฟังก์ชันทั้งสามเป็นสามเธรดเราจำเป็นต้องจัดส่งสามเธรด
int a, b, c;
void geta()
{
a = calculatea();
semaphore_increase();
}
void getb()
{
b = calculateb();
semaphore_increase();
}
void getc()
{
semaphore_decrease();
semaphore_decrease();
c = a + b;
}
t1 = thread_create(geta);
t2 = thread_create(getb);
t3 = thread_create(getc);
thread_join(t3);
ด้วยความช่วยเหลือของสัญญาณรหัสด้านบนสามารถตรวจสอบให้แน่ใจว่าt3
จะไม่ทำงานจนกว่าจะถึงเวลาt1
และt2
ทำงานเสร็จแล้ว
กล่าวได้ว่าเซมาฟอร์คือการทำให้เธรดดำเนินการตามลำดับตรรกะในขณะที่ mutex คือการปกป้องทรัพยากรที่ใช้ร่วมกัน
ดังนั้นจึงไม่เหมือนกันแม้ว่าบางคนมักจะบอกว่า mutex เป็นเซมาฟอร์พิเศษที่มีค่าเริ่มต้น 1 คุณสามารถพูดแบบนี้ได้เช่นกัน แต่โปรดสังเกตว่ามันถูกใช้ในกรณีที่แตกต่างกัน อย่าแทนที่ทีละคนแม้ว่าคุณจะทำได้ก็ตาม
x = getx(); y = gety(); z = x + y;
ด้วยเหตุผลบางประการเราใช้สามเธรดเพื่อทำสามสิ่งนี้ลำดับของเธรดมีความสำคัญมากเพราะเราไม่สามารถทำได้x + y
นอกจากgetx
และgety
เสร็จสิ้นแล้ว ในคำหนึ่งเซมาฟอร์ถูกใช้เมื่อเราสนใจเกี่ยวกับลำดับการทำงานของมัลติเธรด
x
และจะเสร็จสมบูรณ์คำนวณแล้วy
ฉันรู้ว่ามีจาวาz = x + y
CyclicBarrier
นอกจากนี้ฉันไม่แน่ใจว่าฉันสามารถพูดได้ว่าmapreduce
เป็น semaphore usecase ด้วยหรือไม่เพราะฉันทำไม่ได้reduce
จนกว่าmap
จะเสร็จสิ้นทั้งหมด
คำตอบทั้งหมดข้างต้นมีคุณภาพดี แต่คำตอบนี้เป็นเพียงการจดจำชื่อMutexได้มาจากMutually Exclusiveด้วยเหตุนี้คุณจึงมีแรงจูงใจที่จะคิดว่าการล็อค mutex เป็นการกีดกันระหว่างสองคนในครั้งเดียวและถ้าฉัน คุณสามารถครอบครองได้หลังจากที่ฉันปล่อยมันเท่านั้นในทางกลับกันกรณีเช่นนี้ไม่มีอยู่สำหรับSemaphoreก็เหมือนกับสัญญาณจราจร (ซึ่งคำว่า Semaphore ก็หมายถึงเช่นกัน)
ดังที่ได้กล่าวไปแล้วเซมาฟอร์ที่มีการนับหนึ่งเป็นสิ่งเดียวกับเซมาฟอร์ 'ไบนารี' ซึ่งเป็นสิ่งเดียวกับ mutex
สิ่งสำคัญที่ฉันเคยเห็น semaphores ที่มีจำนวนมากกว่าหนึ่งที่ใช้คือสถานการณ์ของผู้ผลิต / ผู้บริโภคที่คุณมีคิวขนาดคงที่ที่แน่นอน
คุณมีเซมาโฟร์สองตัวแล้ว เซมาฟอร์แรกถูกตั้งค่าเป็นจำนวนไอเท็มในคิวในตอนแรกและเซมาฟอร์ที่สองถูกตั้งค่าเป็น 0 ผู้ผลิตทำการดำเนินการ P บนเซมาฟอร์แรกเพิ่มในคิว และทำการ V ในวินาที ผู้บริโภคทำการดำเนินการ P บนเซมาฟอร์ที่สองลบออกจากคิวแล้วทำการดำเนินการ V ในครั้งแรก
ด้วยวิธีนี้ผู้ผลิตจะถูกบล็อกทุกครั้งที่เติมคิวและผู้บริโภคจะถูกบล็อกเมื่อใดก็ตามที่คิวว่างเปล่า
mutex เป็นกรณีพิเศษของเซมาฟอร์ สัญญาณอนุญาตให้หลายเธรดเข้าสู่ส่วนวิกฤต เมื่อสร้างเซมาฟอร์คุณกำหนดว่าจะอนุญาตให้ใช้เธรดได้อย่างไรในส่วนวิกฤต แน่นอนว่าโค้ดของคุณต้องสามารถจัดการการเข้าถึงส่วนสำคัญนี้ได้หลายส่วน
สัญญาณไบนารีและ Mutex แตกต่างกัน จากมุมมองของระบบปฏิบัติการเซมาฟอร์ไบนารีและเซมาฟอร์การนับจะถูกนำไปใช้ในลักษณะเดียวกันและเซมาฟอร์ไบนารีสามารถมีค่า 0 หรือ 1 ได้
Mutex -> สามารถใช้เพื่อจุดประสงค์เดียวในการยกเว้นร่วมกันสำหรับส่วนสำคัญของโค้ดเท่านั้น
สัญญาณ -> สามารถใช้เพื่อแก้ปัญหาต่างๆ สัญญาณไบนารีสามารถใช้สำหรับการส่งสัญญาณและแก้ปัญหาการกีดกันซึ่งกันและกัน เมื่อเริ่มต้นเป็น0จะแก้ปัญหาการส่งสัญญาณและเมื่อเริ่มต้นเป็น1จะแก้ปัญหาการกีดกันซึ่งกันและกันปัญหา
เมื่อจำนวนทรัพยากรมากขึ้นและจำเป็นต้องซิงโครไนซ์เราสามารถใช้สัญญาณการนับ
ในบล็อกของฉันฉันได้พูดถึงหัวข้อเหล่านี้โดยละเอียด
https://designpatterns-oo-cplusplus.blogspot.com/2015/07/synchronization-primitives-mutex-and.html