เธรดการโต้แย้งคืออะไร?


121

ใครช่วยอธิบายง่ายๆว่าการโต้แย้งของเธรดคืออะไร?

ฉัน googled แล้ว แต่ดูเหมือนจะหาคำอธิบายง่ายๆไม่ได้


10
ดังนั้นเขียนว่าความคิดที่คลุมเครือของคุณอยู่ในนั้นเพื่อให้เราได้เห็นว่าคุณอาจจะไม่พอใจหรือความเข้าใจของคุณอาจจะถูกต้อง
James Black

คำตอบ:


89

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


53
คำตอบนี้ไม่สมบูรณ์ (เช่นเดียวกับคนอื่น ๆ ส่วนใหญ่) แม้ว่าแม่กุญแจจะเป็นประเภทหนึ่งที่อาจมีการโต้แย้งได้ แต่ก็ยังห่างไกลจากสิ่งนั้นเพียงอย่างเดียว อาจมีการแย่งชิงทรัพยากรแบบไม่ล็อกได้เช่นกัน (ตัวอย่างเช่นหากเธรดสองเธรดเพิ่มจำนวนเต็มเท่ากันในอะตอมพวกเขาอาจพบข้อขัดแย้งเนื่องจากแคช ping-ponging ไม่มีการล็อกใด ๆ )
David Schwartz

ในกรณีของ Global Interpreter Lock (GIL) เช่นใน CPython ซึ่งเธรดจะต้องได้รับ GIL เสมอเธรดหลายเธรดที่ทำงานในกระบวนการเดียวกันจึงอยู่ในความขัดแย้งโดยค่าเริ่มต้น
Acumenus

ฉันคิดว่าคุณได้อธิบายมันในแง่ของ Deadlock แต่มันแตกต่างจาก Deadlock มาก
Harshit Gupta

185

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

ตัวอย่างที่ชัดเจนที่สุดของการทะเลาะวิวาทอยู่ที่การล็อก หากเธรด A มีการล็อกและเธรด B ต้องการรับล็อกเดียวกันเธรด B จะต้องรอจนกว่าเธรด A จะคลายล็อก

ตอนนี้นี่เป็นเฉพาะแพลตฟอร์ม แต่เธรดอาจพบการชะลอตัวแม้ว่าจะไม่ต้องรอให้เธรดอื่นคลายการล็อก! เนื่องจากการล็อกป้องกันข้อมูลบางประเภทและข้อมูลเองก็มักจะถูกโต้แย้งเช่นกัน

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

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

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

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


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

1
@David โปรดช่วยทำความเข้าใจกับคำตอบสุดท้ายของคุณโดยละเอียด
ผู้เรียน

4
@Naroji ถามคำถามเกี่ยวกับเรื่องนี้
David Schwartz

@DavidSchwartz คุณเป็นโปรแกรมเมอร์ C หรือไม่?
Pacerier

@Pacerier C ++ เป็นส่วนใหญ่
David Schwartz

19

จากที่นี่ :

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

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


นอกจากนี้ยังอธิบายความแตกต่างระหว่างเธรด Contention และ Deadlock
Sankalp

3

ฉันคิดว่าควรมีคำชี้แจงจาก OP เกี่ยวกับพื้นหลังของคำถาม - ฉันคิดได้ 2 คำตอบ (แม้ว่าฉันแน่ใจว่ามีส่วนเพิ่มเติมในรายการนี้):

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

  2. นอกจากนี้ยังมีตัวนับประสิทธิภาพ '.NET CLR Locks and Threads: Total # of Contentions' ตามที่นำมาจากคำอธิบาย PerfMon สำหรับตัวนับนี้ถูกกำหนดเป็น:

    ตัวนับนี้แสดงจำนวนครั้งทั้งหมดที่เธรดใน CLR พยายามรับล็อกที่มีการจัดการไม่สำเร็จ ล็อคที่มีการจัดการสามารถรับได้หลายวิธี โดยคำสั่ง "lock" ใน C # หรือโดยเรียก System.Monitor.Enter หรือโดยใช้ MethodImplOptions.Synchronized แอตทริบิวต์ที่กำหนดเอง

... และฉันแน่ใจว่าคนอื่น ๆ สำหรับ OS'es และกรอบแอปพลิเคชันอื่น ๆ


2

คุณมี 2 กระทู้ เธรด A และเธรด B คุณยังมีวัตถุ C

ขณะนี้ A กำลังเข้าถึงวัตถุ C และได้ทำการล็อควัตถุนั้น B ต้องการเข้าถึงวัตถุ C แต่ไม่สามารถทำได้จนกว่า A จะปลดล็อกวัตถุ C


1

อีกคำหนึ่งอาจเกิดขึ้นพร้อมกัน เป็นเพียงความคิดของเธรดสองชุดขึ้นไปที่พยายามใช้ทรัพยากรเดียวกัน


1

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


1

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

ดังตัวอย่างทั้งสองกรณีให้ความหมายของการแข่งขันกัน


0

การช่วงชิงเธรดยังมีผลต่อการดำเนินการ I / O ตัวอย่างเมื่อเธรดที่รอการอ่านไฟล์สามารถพิจารณาได้ว่าเป็นการโต้แย้ง ใช้พอร์ตเสร็จสิ้น I / O เป็นโซลูชัน


0

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

จากเอกสาร dotTrace

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