เธรด (คอมพิวเตอร์)

จากวิกิพีเดีย สารานุกรมเสรี
ข้ามไปที่การนำทาง ข้ามไปที่การค้นหา
กระบวนการที่มีการดำเนินการสองเธรด ทำงานบนโปรเซสเซอร์ตัว เดียว

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

ประวัติ

Threads ปรากฏตัวครั้งแรกภายใต้ชื่อ "tasks" ในOS/360 Multiprogramming with a Variable Number of Tasks (MVT) ในปี 1967 Saltzer (1966) ให้เครดิตVictor A. Vyssotskyกับคำว่า "thread" [2]

ความนิยมของเธรดเพิ่มขึ้นประมาณปี 2546 เนื่องจากการเติบโตของความถี่ CPU ถูกแทนที่ด้วยจำนวนคอร์ที่เพิ่มขึ้น ส่งผลให้ต้องใช้การทำงานพร้อมกันหลายคอร์ [3]

กระบวนการ เคอร์เนลเธรด เธรดผู้ใช้ และไฟเบอร์

การจัดกำหนดการสามารถทำได้ที่ระดับเคอร์เนลหรือระดับผู้ใช้ และการทำงานหลายอย่างสามารถทำได้ล่วงหน้าหรือร่วมมือกัน ทำให้เกิดแนวคิดที่เกี่ยวข้องที่หลากหลาย

กระบวนการ

ที่ระดับเคอร์เนลกระบวนการประกอบด้วยหนึ่งหรือหลายเคอร์เนลเธรดซึ่งแบ่งใช้ทรัพยากรของกระบวนการ เช่น หน่วยความจำและตัวจัดการไฟล์ – กระบวนการคือหน่วยของทรัพยากร ในขณะที่เธรดคือหน่วยของการจัดกำหนดการและการดำเนินการ โดยทั่วไปการจัดกำหนดการเคอร์เนลจะทำแบบเดียวกันโดยยึดเอาเปรียบหรือให้ความร่วมมือน้อยกว่า ที่ระดับผู้ใช้ กระบวนการเช่นระบบรันไทม์สามารถกำหนดเวลาการดำเนินการได้หลายเธรด หากสิ่งเหล่านี้ไม่แบ่งปันข้อมูล เช่นเดียวกับใน Erlang พวกเขามักจะถูกเรียกว่ากระบวนการคล้ายคลึงกัน[4]ในขณะที่หากพวกเขาแบ่งปันข้อมูลมักจะเรียกว่า(ผู้ใช้) เธรดโดยเฉพาะอย่างยิ่งหากกำหนดเวลาไว้ล่วงหน้า เธรดผู้ใช้ที่กำหนดเวลาร่วมกันเรียกว่าไฟเบอร์; กระบวนการที่แตกต่างกันอาจกำหนดเวลาเธรดผู้ใช้ต่างกัน เธรดผู้ใช้อาจถูกเรียกใช้งานโดยเคอร์เนลเธรดได้หลายวิธี (หนึ่งต่อหนึ่ง หลายต่อหนึ่ง หลายต่อหลาย) คำว่า " กระบวนการน้ำหนักเบา " ต่าง ๆ หมายถึงเธรดผู้ใช้หรือกลไกเคอร์เนลสำหรับการจัดกำหนดการเธรดผู้ใช้บนเธรดเคอร์เนล

โปรเซ ส คือหน่วย "เฮฟวี่เวท" ของการตั้งเวลาเคอร์เนล เนื่องจากกระบวนการสร้าง ทำลาย และสับเปลี่ยนค่อนข้างแพง ประมวล ผล ทรัพยากร ของตัวเองที่ จัดสรรโดยระบบปฏิบัติการ ทรัพยากรรวมถึงหน่วยความจำ (สำหรับทั้งโค้ดและข้อมูล) ตัวจัดการไฟล์ซ็อกเก็ต หมายเลขอ้างอิงอุปกรณ์ windows และบล็อกควบคุมกระบวนการ กระบวนการถูกแยกโดยการแยกกระบวนการและไม่แชร์พื้นที่ที่อยู่หรือทรัพยากรไฟล์ ยกเว้นผ่านวิธีการที่ชัดเจน เช่น การสืบทอดการจัดการไฟล์หรือเซ็กเมนต์หน่วยความจำที่ใช้ร่วมกัน หรือการแมปไฟล์เดียวกันในลักษณะที่ใช้ร่วมกัน – ดูการสื่อสารระหว่างกระบวนการ. การสร้างหรือทำลายกระบวนการค่อนข้างแพง เนื่องจากต้องได้รับหรือปล่อยทรัพยากร โดยทั่วไป กระบวนการจะทำงานหลายอย่างพร้อมกัน และการสลับกระบวนการค่อนข้างแพง นอกเหนือไปจากต้นทุนพื้นฐานของการสลับบริบทเนื่องจากปัญหาต่างๆ เช่น การล้างแคช (โดยเฉพาะอย่างยิ่ง การสลับกระบวนการเปลี่ยนที่อยู่หน่วยความจำเสมือน ทำให้เกิดการใช้งานไม่ได้ และล้างบัฟเฟอร์การแปล ที่ไม่ได้ติดแท็ก , โดยเฉพาะอย่างยิ่งใน x86)

เธรดเคอร์เนล

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

กระทู้ของผู้ใช้

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

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

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

วิธีแก้ปัญหาทั่วไปสำหรับปัญหานี้ (โดยเฉพาะอย่างยิ่ง การใช้งานเธรดสีเขียวจำนวนมาก) คือการจัดเตรียม I/O API ที่ใช้อินเทอร์เฟซที่บล็อกเธรดที่เรียก แทนที่จะเป็นกระบวนการทั้งหมด โดยใช้ I/O ที่ไม่บล็อก ภายในและกำหนดเวลาเธรดผู้ใช้หรือไฟเบอร์อื่นในขณะที่ดำเนินการ I/O สามารถจัดเตรียมวิธีแก้ปัญหาที่คล้ายกันสำหรับการเรียกระบบบล็อกอื่นๆ อีกทางหนึ่ง สามารถเขียนโปรแกรมเพื่อหลีกเลี่ยงการใช้ซิงโครนัส I/O หรือการเรียกระบบบล็อกอื่น ๆ (โดยเฉพาะอย่างยิ่ง การใช้ I/O ที่ไม่ปิดกั้น รวมถึงการต่อเนื่องของแลมบ์ดาและ/หรือ async/ กำลังรอพื้นฐาน[5] )

เส้นใย

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

เธรดเทียบกับกระบวนการ

เธรดแตกต่างจากกระบวนการของระบบปฏิบัติการมัลติทาสกิ้ง แบบดั้งเดิม ในหลายวิธี:

ระบบเช่นWindows NTและOS/2มีการกล่าวกันว่ามีเธรดราคาถูก และ กระบวนการ ที่ มีราคาแพง ในระบบปฏิบัติการอื่น ๆ ไม่มีความแตกต่างมากนักยกเว้นในค่าใช้จ่ายของ สวิตช์ พื้นที่ที่อยู่ซึ่งในสถาปัตยกรรมบางอย่าง (โดยเฉพาะx86 ) ส่งผลให้เกิดการ ล้าง บัฟเฟอร์ lookaside (TLB)

ข้อดีและข้อเสียของเธรดเทียบกับกระบวนการ ได้แก่:

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

กำหนดการ

การวางกำหนดการเทียบกับกำหนดการแบบร่วมมือ

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

ระบบตัวเดียวและหลายตัวประมวลผล

จนถึงช่วงต้นทศวรรษ 2000 คอมพิวเตอร์เดสก์ท็อปส่วนใหญ่มี CPU แบบ single-core เพียงตัวเดียว โดยไม่รองรับเธรดฮาร์ดแวร์แม้ว่าเธรดจะยังคงถูกใช้บนคอมพิวเตอร์ดังกล่าว เนื่องจากโดยทั่วไปการสลับระหว่างเธรดยังเร็วกว่าการสลับบริบทแบบ เต็มกระบวนการ ในปี 2545 Intelได้เพิ่มการสนับสนุนสำหรับโปรเซสเซอร์Pentium 4 แบบมัลติเธรดพร้อมกันภายใต้ชื่อhyper-threading ; ในปี 2548 พวกเขาได้เปิดตัวโปรเซสเซอร์ Pentium D แบบดูอัลคอร์ และAMDได้เปิดตัวโปรเซสเซอร์ Athlon 64 X2 แบบดูอัลคอ ร์

ระบบที่ใช้โปรเซสเซอร์ตัวเดียวโดยทั่วไปจะใช้มัลติเธรดโดยการแบ่งเวลา : หน่วยประมวลผลกลาง (CPU) จะสลับไปมาระหว่างซอฟต์แวร์เธรดต่างๆ การ สลับบริบทนี้มักจะเกิดขึ้นบ่อยครั้งมากพอที่ผู้ใช้จะรับรู้เธรดหรืองานว่าทำงานพร้อมกัน (สำหรับระบบปฏิบัติการเซิร์ฟเวอร์/เดสก์ท็อปยอดนิยม การแบ่งเวลาสูงสุดของเธรด เมื่อเธรดอื่นกำลังรอ มักจะจำกัดที่ 100-200 มิลลิวินาที) บนระบบมัลติโปรเซสเซอร์หรือมัลติคอร์ หลายเธรดสามารถรันแบบขนานโดยที่ทุกโปรเซสเซอร์หรือคอร์รันเธรดแยกกัน บนโปรเซสเซอร์หรือคอร์ที่มีเธรดฮาร์ดแวร์นอกจากนี้ยังสามารถเรียกใช้เธรดซอฟต์แวร์ที่แยกจากกันโดยใช้เธรดฮาร์ดแวร์ที่แยกจากกัน

แบบเกลียว

1:1 (เธรดระดับเคอร์เนล)

เธรดที่สร้างโดยผู้ใช้ในการโต้ตอบแบบ 1:1 กับเอนทิตีที่ตั้งเวลาได้ในเคอร์เนล[6]เป็นการใช้งานเธรดที่ง่ายที่สุด OS/2และWin32ใช้วิธีการนี้ตั้งแต่เริ่มต้น ในขณะที่บนLinux GNU C Libraryใช้วิธีนี้ (ผ่านNPTLหรือLinuxThreads ที่เก่ากว่า ) วิธี การ นี้ยังใช้โดยSolaris , NetBSD , FreeBSD , macOSและiOS

N : 1 (เธรดระดับผู้ใช้)

โมเดล N :1 บ่งบอกว่าเธรดระดับ แอปพลิเคชันทั้งหมดแมปกับเอนทิตีที่จัดกำหนดการไว้ระดับเคอร์เนลหนึ่งรายการ [6]เคอร์เนลไม่มีความรู้เกี่ยวกับเธรดแอปพลิเคชัน ด้วยวิธีนี้ การสลับบริบทสามารถทำได้อย่างรวดเร็ว และนอกจากนี้ ยังสามารถใช้งานได้แม้ในเมล็ดธรรมดาที่ไม่รองรับการทำเธรด อย่างไรก็ตาม ข้อเสียที่สำคัญประการหนึ่งก็คือ มันไม่ได้รับประโยชน์จากการเร่งความเร็วด้วยฮาร์ดแวร์บนโปรเซสเซอร์แบบมัลติเธรด หรือคอมพิวเตอร์ที่มีโปรเซสเซอร์ หลายตัว : ไม่มีการกำหนดเวลามากกว่าหนึ่งเธรดในเวลาเดียวกัน [6]ตัวอย่างเช่น: หากเธรดใดเธรดหนึ่งจำเป็นต้องดำเนินการตามคำขอ I/O กระบวนการทั้งหมดจะถูกบล็อกและไม่สามารถใช้ข้อได้เปรียบของเธรดได้ ดิGNU Portable Threadsใช้เธรดระดับผู้ใช้ เช่นเดียวกับState Threads

M : N (การทำเกลียวแบบไฮบริด)

M : NแมปจำนวนเธรดแอปพลิเคชันM จำนวนหนึ่ง กับเอนทิตีเคอร์เนลจำนวนN บางตัว [6]หรือ "ตัวประมวลผลเสมือน" นี่คือการประนีประนอมระหว่างเธรดระดับเคอร์เนล ("1:1") และระดับผู้ใช้ (" N :1") โดยทั่วไป ระบบเธรด " M : N " มีความซับซ้อนในการใช้งานมากกว่าเคอร์เนลหรือเธรดผู้ใช้ เนื่องจากจำเป็นต้องมีการเปลี่ยนแปลงทั้งเคอร์เนลและโค้ดพื้นที่ผู้ใช้[ จำเป็นต้อง ชี้แจง ]. ในการใช้งาน M:N ไลบรารีเธรดมีหน้าที่จัดกำหนดการเธรดผู้ใช้บนเอนทิตีที่จัดกำหนดการได้ ทำให้การสลับบริบทของเธรดเป็นไปอย่างรวดเร็ว เนื่องจากจะหลีกเลี่ยงการเรียกของระบบ อย่างไรก็ตาม สิ่งนี้จะเพิ่มความซับซ้อนและความน่าจะเป็นของการผกผันของลำดับความสำคัญตลอดจนการจัดกำหนดการที่ไม่เหมาะสมโดยไม่มีการประสานงานที่กว้างขวาง (และมีราคาแพง) ระหว่างตัวจัดกำหนดการ userland และตัวกำหนดตารางเวลาเคอร์เนล

ตัวอย่างการใช้งานแบบไฮบริด

  • การเปิดใช้งานตัวกำหนดเวลาที่ใช้โดยการใช้ไลบรารี่เธรด POSIX ดั้งเดิมของ NetBSD เวอร์ชันเก่า ( โมเดล M : Nตรงข้ามกับเคอร์เนล 1:1 หรือโมเดลการใช้งานพื้นที่ผู้ใช้)
  • กระบวนการน้ำหนักเบาที่ ใช้โดย ระบบปฏิบัติการSolarisเวอร์ชันเก่า
  • Marcel จากโครงการPM2
  • ระบบปฏิบัติการสำหรับ Tera- Cray MTA-2
  • Glasgow Haskell Compiler (GHC) สำหรับภาษาHaskell ใช้เธรดที่มีน้ำหนักเบาซึ่งกำหนดตารางเวลาไว้บนเธรดของระบบปฏิบัติการ

ประวัติการสร้างเธรดในระบบ Unix

SunOS 4.x ใช้กระบวนการน้ำหนักเบาหรือ LWP NetBSD 2.x+ และDragonFly BSDใช้ LWP เป็นเคอร์เนลเธรด (รุ่น 1:1) SunOS 5.2 ถึง SunOS 5.8 และ NetBSD 2 ถึง NetBSD 4 ใช้โมเดลสองระดับ มัลติเพล็กซ์ระดับผู้ใช้หนึ่งเธรดขึ้นไปในแต่ละเคอร์เนลเธรด (รุ่น M:N) SunOS 5.9 และใหม่กว่า รวมถึง NetBSD 5 ได้ยกเลิกการสนับสนุนเธรดของผู้ใช้ กลับไปเป็นรุ่น 1:1 [7] FreeBSD 5 ใช้โมเดล M:N FreeBSD 6 รองรับทั้ง 1:1 และ M:N ผู้ใช้สามารถเลือกได้ว่าควรใช้โปรแกรมใดกับโปรแกรมที่กำหนดโดยใช้ /etc/libmap.conf เริ่มต้นด้วย FreeBSD 7 1:1 กลายเป็นค่าเริ่มต้น FreeBSD 8 ไม่รองรับรุ่น M:N อีกต่อไป

โปรแกรมแบบเธรดเดียวและแบบมัลติเธรด

ในการเขียนโปรแกรมคอมพิวเตอร์เธรดเดียวคือการประมวลผลคำสั่งครั้ง ละหนึ่งคำสั่ง [8] ในการวิเคราะห์อย่างเป็นทางการของ ความหมายของตัวแปรและสถานะกระบวนการ คำว่าsingle threadingสามารถใช้แตกต่างกันเพื่อหมายถึง "backtracking ภายในเธรดเดียว" ซึ่งเป็นเรื่องปกติในชุมชนการเขียนโปรแกรมเชิงฟังก์ชัน [9]

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

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

เธรดและการซิงโครไนซ์ข้อมูล

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

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

API การซิงโครไนซ์อื่นๆ ได้แก่ตัวแปรเงื่อนไขส่วนที่สำคัญสัญญาณและการ มอนิเตอร์

กลุ่มกระทู้

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

โปรแกรม Multithreaded กับโปรแกรม single-threaded ข้อดีและข้อเสีย

แอปพลิเคชันแบบมัลติเธรดมีข้อดีดังต่อไปนี้เมื่อเทียบกับแอปพลิเคชันแบบเธรดเดียว:

  • การ ตอบสนอง : มัลติเธรดสามารถช่วยให้แอปพลิเคชันยังคงตอบสนองต่ออินพุตได้ ในโปรแกรมแบบเธรดเดียว หากเธรดการดำเนินการหลักบล็อกงานที่ใช้เวลานาน แอปพลิเคชันทั้งหมดอาจหยุดทำงาน ด้วยการย้ายงานที่ใช้เวลานานดังกล่าวไปยังเธรดของผู้ปฏิบัติงานที่ทำงานพร้อมกันกับเธรดการดำเนินการหลัก เป็นไปได้ที่แอปพลิเคชันจะยังคงตอบสนองต่ออินพุตของผู้ใช้ในขณะที่รันงานในเบื้องหลัง ในทางกลับกัน ในกรณีส่วนใหญ่ มัลติเธรดไม่ได้เป็นเพียงวิธีเดียวที่จะทำให้โปรแกรมตอบสนองได้ โดยมี สัญญาณ I/Oและ/หรือUnix ที่ไม่มีการบล็อก เพื่อให้ได้ผลลัพธ์ที่คล้ายคลึงกัน [10]
  • Parallelization : แอปพลิเคชันที่ต้องการใช้ระบบมัลติคอร์หรือหลายซีพียูสามารถใช้มัลติเธรดเพื่อแยกข้อมูลและงานออกเป็นงานย่อยแบบขนาน และให้สถาปัตยกรรมพื้นฐานจัดการวิธีการทำงานของเธรด ไม่ว่าจะทำงานพร้อมกันบนคอร์เดียวหรือหลายคอร์พร้อมกัน สภาพแวดล้อมการประมวลผลของ GPU เช่นCUDAและOpenCLใช้โมเดลมัลติเธรดซึ่งมีเธรดหลายสิบถึงร้อยเธรดที่ทำงานคู่ขนานกันในข้อมูลบนคอร์จำนวนมาก ในทางกลับกัน ช่วยให้สามารถใช้ระบบได้ดีขึ้น และ (โดยมีเงื่อนไขว่าค่าใช้จ่ายในการซิงโครไนซ์ไม่กินประโยชน์) สามารถให้การดำเนินการโปรแกรมเร็วขึ้น

แอปพลิเคชันแบบมัลติเธรดมีข้อเสียดังต่อไปนี้:

  • ความซับซ้อนของ การซิงโครไนซ์และจุดบกพร่องที่เกี่ยวข้อง: เมื่อใช้ทรัพยากรที่ใช้ร่วมกันโดยทั่วไปสำหรับโปรแกรมแบบเธรดโปรแกรมเมอร์จะต้องระมัดระวังเพื่อหลีกเลี่ยงสภาวะการแข่งขันและพฤติกรรมอื่นๆ ที่ไม่เป็นไปตามสัญชาตญาณ เพื่อให้มีการจัดการข้อมูลอย่างถูกต้อง เธรดมักจะต้องนัดพบเพื่อประมวลผลข้อมูลในลำดับที่ถูกต้อง เธรดอาจต้องการ การดำเนินการที่ไม่เกิด ร่วมกัน (มักใช้งานโดยใช้ mutexes ) เพื่อป้องกันไม่ให้ข้อมูลทั่วไปถูกอ่านหรือเขียนทับในเธรดหนึ่งในขณะที่มีการแก้ไขโดยอีกเธรดหนึ่ง การใช้พื้นฐานดังกล่าวโดยประมาทอาจนำไปสู่การหยุดชะงักสิ่งมีชีวิต หรือการแข่งขัน แย่งชิง ทรัพยากร รับบท เอ็ดเวิร์ด เอ . ลีได้เขียนไว้ว่า: "แม้ว่าเธรดจะดูเหมือนเป็นขั้นตอนเล็ก ๆ จากการคำนวณตามลำดับ แต่อันที่จริงแล้วมันเป็นขั้นตอนที่ยิ่งใหญ่ พวกเขาละทิ้งคุณสมบัติที่สำคัญและน่าสนใจที่สุดของการคำนวณตามลำดับ: ความเข้าใจ ความสามารถในการคาดการณ์ และการกำหนด เธรดเป็นแบบจำลองของ การคำนวณนั้นไม่มีการกำหนดอย่างเด็ดขาด และงานของโปรแกรมเมอร์ก็กลายเป็นหนึ่งในการตัดทอนความไม่กำหนดนั้น" (11)
  • ไม่สามารถทดสอบได้ โดยทั่วไป โปรแกรมแบบมัลติเธรดจะไม่ถูกกำหนด และเป็นผลให้ไม่สามารถทดสอบได้ กล่าวอีกนัยหนึ่ง โปรแกรมแบบมัลติเธรดสามารถมีจุดบกพร่องที่ไม่เคยปรากฏบนระบบทดสอบได้อย่างง่ายดาย ซึ่งแสดงเฉพาะในการผลิตเท่านั้น [12] [11]สิ่งนี้สามารถบรรเทาได้โดยการจำกัดการสื่อสารระหว่างเธรดให้เป็นรูปแบบที่กำหนดไว้อย่างดี (เช่น การส่งข้อความ)
  • ค่าใช้จ่ายในการซิงโครไนซ์ เนื่องจากสวิตช์บริบทของเธรดบน CPU สมัยใหม่อาจมีราคาสูงถึง 1 ล้านรอบของ CPU [13]ทำให้การเขียนโปรแกรมมัลติเธรดที่มีประสิทธิภาพนั้นทำได้ยาก โดยเฉพาะอย่างยิ่ง ต้องให้ความสนใจเป็นพิเศษเพื่อหลีกเลี่ยงการซิงโครไนซ์ระหว่างเธรดบ่อยเกินไป

รองรับภาษาโปรแกรม

ภาษาโปรแกรมหลายภาษารองรับเธรดในบางพื้นที่

  • IBM PL/I (F) รวมการสนับสนุนสำหรับมัลติเธรด (เรียกว่ามัลติทาสกิ้ง ) ตั้งแต่ต้นทศวรรษ 1960 และสิ่งนี้ยังคงดำเนินต่อไปใน Optimizing Compiler และเวอร์ชันที่ใหม่กว่า คอมไพเลอร์ IBM Enterprise PL/I แนะนำ API "เธรด" รุ่นใหม่ ไม่มีเวอร์ชันใดเป็นส่วนหนึ่งของมาตรฐาน PL/I
  • การใช้งานCและC++ จำนวนมาก รองรับเธรด และให้การเข้าถึง API เธรดดั้งเดิมของระบบปฏิบัติการ อินเทอร์เฟซมาตรฐานสำหรับการใช้งานเธรดคือPOSIX Threads (Pthreads) ซึ่งเป็นชุดของการเรียกไลบรารีฟังก์ชัน C ผู้จำหน่ายระบบปฏิบัติการสามารถใช้อินเทอร์เฟซได้ตามต้องการ แต่นักพัฒนาแอปพลิเคชันควรสามารถใช้อินเทอร์เฟซเดียวกันในหลายแพลตฟอร์มได้ แพลตฟอร์ม Unixส่วนใหญ่รวมถึง Linux รองรับ Pthreads Microsoft Windows มีชุดฟังก์ชันเธรดของตัวเองใน อินเทอร์เฟซ process.h สำหรับมัลติ เธรดเช่นstartthread
  • ภาษาโปรแกรม ระดับสูงบาง ภาษา (และโดยปกติข้ามแพลตฟอร์ม ) เช่นJava , Pythonและ.NET Frameworkจะเปิดเผยเธรดต่อนักพัฒนาในขณะที่แยกแยะความแตกต่างเฉพาะของแพลตฟอร์มในการใช้งานเธรดในรันไทม์ ภาษาโปรแกรมและส่วนขยายภาษาอื่นๆ อีกหลายภาษายังพยายามสรุปแนวคิดเรื่องการทำงานพร้อมกันและเธรดจากนักพัฒนาอย่างสมบูรณ์ ( Cilk , OpenMP , Message Passing Interface (MPI)) บางภาษาได้รับการออกแบบสำหรับการขนานกันตามลำดับแทน (โดยเฉพาะการใช้ GPU) โดยไม่ต้องมีการทำงานพร้อมกันหรือเธรด ( Ateji PX , CUDA).
  • ภาษาโปรแกรมที่แปลแล้วสองสามภาษามีการใช้งาน (เช่นRuby MRIสำหรับ Ruby, CPythonสำหรับ Python) ซึ่งรองรับการทำเธรดและการทำงานพร้อมกัน แต่ไม่ใช่การรันเธรดแบบขนานเนื่องจากการล็อกตัวแปลทั่วโลก (GIL) GIL เป็นการล็อกการยกเว้นร่วมกันที่ถือโดยล่าม ซึ่งสามารถป้องกันไม่ให้ล่ามแปลรหัสแอปพลิเคชันพร้อมกันบนเธรดสองตัวหรือมากกว่าในคราวเดียว ซึ่งจะจำกัดการขนานกันในระบบแกนหลักหลายระบบอย่างมีประสิทธิภาพ ซึ่งจำกัดประสิทธิภาพการทำงานส่วนใหญ่สำหรับเธรดที่ผูกกับโปรเซสเซอร์ ซึ่งต้องการโปรเซสเซอร์ และไม่มากสำหรับเธรดที่ผูกกับ I/O หรือเครือข่าย การใช้งานอื่นๆ ของภาษาโปรแกรมที่ตีความ เช่นTclใช้ส่วนขยายของเธรด หลีกเลี่ยงขีดจำกัด GIL โดยใช้โมเดล Apartment ซึ่งต้อง "แชร์" ข้อมูลและรหัสระหว่างเธรดอย่างชัดเจน ใน Tcl แต่ละเธรดมีล่ามหนึ่งตัวหรือมากกว่า
  • ในโมเดลการเขียนโปรแกรม เช่นCUDA ที่ ออกแบบมาสำหรับการคำนวณข้อมูลแบบขนานอาร์เรย์ของเธรดจะรันโค้ดเดียวกันแบบขนานโดยใช้ ID เท่านั้นเพื่อค้นหาข้อมูลในหน่วยความจำ โดยพื้นฐานแล้ว แอปพลิเคชันต้องได้รับการออกแบบเพื่อให้แต่ละเธรดทำงานเหมือนกันในส่วนต่างๆ ของหน่วยความจำ เพื่อให้สามารถทำงานแบบคู่ขนานและใช้สถาปัตยกรรม GPU ได้
  • ภาษาคำอธิบายฮาร์ดแวร์เช่นVerilogมีรุ่นเธรดที่แตกต่างกันซึ่งรองรับเธรดจำนวนมาก (สำหรับการสร้างโมเดลฮาร์ดแวร์)

ดูเพิ่มเติม

อ้างอิง

  1. แลมพอร์ต, เลสลี่ (กันยายน 2522) "วิธีสร้างคอมพิวเตอร์มัลติโปรเซสเซอร์ที่รันโปรแกรมหลายโปรเซสเซอร์อย่างถูกต้อง" (PDF ) ธุรกรรม IEEE บนคอมพิวเตอร์ C-28 (9): 690–691 ดอย : 10.1109/tc.1979.1675439 . S2CID  5679366 .
  2. ^ Traffic Control in a Multiplexed Computer System , Jerome Howard Saltzer , วิทยานิพนธ์ดุษฎีบัณฑิต , 1966, ดูเชิงอรรถในหน้า 20.
  3. ^ สมุนไพรซัทเทอร์ . "การรับประทานอาหารกลางวันฟรีสิ้นสุดลงแล้ว: การเปลี่ยนแปลงขั้นพื้นฐานสู่การทำงานพร้อมกันในซอฟต์แวร์ "
  4. ^ "Erlang: 3.1 กระบวนการ" .
  5. เซอร์เกย์ อิกัตเชนโก้. "แปดวิธีในการจัดการการส่งคืนแบบไม่ปิดกั้นในโปรแกรมส่งข้อความ: จาก C++98 ผ่าน C++11 ถึง C++20 " ซีพีคอน. เก็บถาวรจากต้นฉบับเมื่อ 2021-11-04
  6. a b c d Gagne, Abraham Silberschatz, Peter Baer Galvin, Greg (2013). แนวคิดระบบปฏิบัติการ (ฉบับที่ 9) โฮโบเกน รัฐนิวเจอร์ซี: ไวลีย์ หน้า 170–171. ISBN 9781118063330.
  7. ^ "มัลติเธรดในสภาพแวดล้อมการทำงาน Solaris" (PDF ) 2545 เก็บถาวรจากต้นฉบับ(PDF)เมื่อวันที่ 26 กุมภาพันธ์ 2552
  8. ราอูล เมเนนเดซ; ดั๊ก โลว์ (2001). CICS ของ Murach สำหรับโปรแกรมเมอร์ภาษาโคบอลต์ ไมค์ มูรัค แอนด์ แอสโซซิเอตส์ หน้า 512. ISBN 978-1-890774-09-7.
  9. ปีเตอร์ วิลเลียม โอเฮิร์น; RD Tennent (1997). ภาษาคล้าย ALGOL ฉบับที่ 2. Birkhäuser Verlag . หน้า 157. ISBN 978-0-8176-3937-2.
  10. เซอร์เกย์ อิกัตเชนโก้. "เธรดเดียว: กลับสู่อนาคต?" . โอเวอร์โหลด (97)
  11. อรรถเป็น เอ็ดเวิร์ด ลี (10 มกราคม 2549) "ปัญหากระทู้" . ยูซี เบิร์กลีย์.
  12. ^ "มัลติเธรดในระดับตรรกะทางธุรกิจถือว่าเป็นอันตราย " เอซีซียู
  13. ^ 'กระต่ายไม่มีแมลง' "ค่าใช้จ่ายในการดำเนินการในวงจรนาฬิกา ของCPU"

อ่านเพิ่มเติม

  • David R. Butenhof: การเขียนโปรแกรมด้วย POSIX Threads , Addison-Wesley, ISBN 0-201-63392-2 
  • Bradford Nichols, Dick Buttlar, Jacqueline Proulx Farell: การเขียนโปรแกรม Pthreads , O'Reilly & Associates, ISBN 1-56592-115-1 
  • Paul Hyde: การเขียนโปรแกรมเธรด Java , Sams, ISBN 0-672-31585-8 
  • Jim Beveridge, Robert Wiener: แอปพลิเคชั่นมัลติเธรดใน Win32 , Addison-Wesley, ISBN 0-201-44234-5 
  • Uresh Vahalia: Unix Internals: พรมแดนใหม่ , Prentice Hall, ISBN 0-13-101908-2