ฉันคิดว่าจุดของคอมพิวเตอร์แบบมัลติคอร์คือมันสามารถรันหลายเธรดพร้อมกันได้ ในกรณีนั้นถ้าคุณมีเครื่อง quad-core จุดที่มีเธรดมากกว่า 4 เธรดทำงานอยู่ในเวลาใด พวกเขาจะไม่เพียงขโมยเวลา (ทรัพยากร CPU) จากกันและกันหรือไม่
ฉันคิดว่าจุดของคอมพิวเตอร์แบบมัลติคอร์คือมันสามารถรันหลายเธรดพร้อมกันได้ ในกรณีนั้นถ้าคุณมีเครื่อง quad-core จุดที่มีเธรดมากกว่า 4 เธรดทำงานอยู่ในเวลาใด พวกเขาจะไม่เพียงขโมยเวลา (ทรัพยากร CPU) จากกันและกันหรือไม่
คำตอบ:
คำตอบหมุนรอบวัตถุประสงค์ของเธรดซึ่งขนานกัน: เพื่อรันหลายบรรทัดของการดำเนินการในคราวเดียว ในระบบ 'อุดมคติ' คุณจะมีหนึ่งเธรดที่ดำเนินการต่อคอร์: ไม่มีการหยุดชะงัก ในความเป็นจริงนี่ไม่ใช่กรณี แม้ว่าคุณจะมีสี่คอร์และเธรดการทำงานสี่เธรดกระบวนการของคุณและเธรดนั้นจะถูกสลับไปใช้สำหรับกระบวนการและเธรดอื่น ๆ อยู่ตลอดเวลา หากคุณใช้ระบบปฏิบัติการที่ทันสมัยทุกกระบวนการมีอย่างน้อยหนึ่งเธรดและอีกหลายมีเพิ่มเติม กระบวนการทั้งหมดนี้ทำงานพร้อมกัน คุณอาจมีหลายร้อยกระทู้ทั้งหมดที่ทำงานบนเครื่องของคุณตอนนี้ คุณจะไม่ได้รับสถานการณ์ที่เธรดรันโดยไม่มีเวลา 'ขโมย' จากมัน (ถ้าอย่างนั้นคุณอาจใช้มันแบบเรียลไทม์ไปได้ถ้าคุณใช้ระบบปฏิบัติการเรียลไทม์หรือแม้กระทั่งบน Windows ใช้ลำดับความสำคัญของเธรดแบบเรียลไทม์ แต่มันหายาก)
กับที่เป็นพื้นหลังคำตอบ: ใช่มากกว่าสี่หัวข้อบนเครื่องสี่หลักความจริงอาจทำให้คุณสถานการณ์ที่พวกเขาขโมยเวลาจากกัน ' แต่ถ้าแต่ละหัวข้อของแต่ละบุคคลต้องการ CPU ถ้าเธรดใช้งานไม่ได้ 100% (เนื่องจากเธรด UI อาจไม่ทำงานหรือเธรดทำงานเล็กน้อยหรือรออย่างอื่น) เธรดอื่นที่กำลังจัดกำหนดการเป็นจริงสถานการณ์ที่ดี
จริงๆแล้วมันซับซ้อนกว่านั้น:
ถ้าคุณมีงานห้าชิ้นที่ต้องทำพร้อมกันล่ะ มันสมเหตุสมผลกว่าที่จะเรียกใช้พวกมันทั้งหมดในครั้งเดียวแทนที่จะวิ่งสี่คนแล้ววิ่งห้าในภายหลัง
มันหายากสำหรับเธรดที่ต้องการ CPU 100% อย่างแท้จริง ทันทีที่มันใช้ดิสก์หรือ I / O เครือข่ายตัวอย่างเช่นอาจใช้เวลาในการรอทำอะไรที่มีประโยชน์ นี่เป็นสถานการณ์ที่พบบ่อยมาก
หากคุณมีงานที่จำเป็นต้องเรียกใช้กลไกทั่วไปอย่างใดอย่างหนึ่งคือการใช้เธรดพูล มันอาจดูเหมือนจะทำให้ความรู้สึกที่มีหมายเลขเดียวกันของหัวข้อเป็นแกนยังอยู่ NET threadpool มีถึง 250 หัวข้อใช้ได้ต่อโปรเซสเซอร์ ฉันไม่แน่ใจว่าทำไมพวกเขาทำเช่นนี้ แต่ฉันเดาว่าจะทำอย่างไรกับขนาดของงานที่ได้รับมอบหมายให้ทำงานในกระทู้
ดังนั้น: เวลาในการขโมยไม่ใช่สิ่งเลวร้าย (และไม่ได้ขโมยจริงๆเช่นกัน: มันเป็นวิธีที่ระบบควรจะทำงาน) เขียนโปรแกรมแบบมัลติเธรดของคุณตามประเภทงานที่เธรดจะทำซึ่งอาจไม่ใช่ซีพียู -bound กำหนดจำนวนเธรดที่คุณต้องการตามการทำโปรไฟล์และการวัด คุณอาจพบว่ามีประโยชน์มากกว่าที่จะคิดในแง่ของงานหรืองานแทนที่จะเป็นเธรด: เขียนออบเจ็กต์ของงานและมอบให้กับกลุ่มที่จะเรียกใช้ สุดท้ายยกเว้นว่าโปรแกรมของคุณมีความสำคัญต่อประสิทธิภาพอย่างแท้จริงไม่ต้องกังวลมากเกินไป :)
เพียงเพราะมีเธรดอยู่ไม่ได้หมายความว่ามันจะทำงานอยู่ แอปพลิเคชันของเธรดจำนวนมากเกี่ยวข้องกับเธรดบางส่วนที่จะเข้าสู่โหมดสลีจนกระทั่งถึงเวลาที่พวกเขาจะทำอะไรบางอย่างเช่นอินพุทของผู้ใช้ที่กระตุ้นให้เธรดเริ่มทำงานการประมวลผลและกลับไปนอน
โดยพื้นฐานแล้วเธรดเป็นงานเดี่ยวที่สามารถทำงานได้อย่างเป็นอิสระจากกันโดยไม่จำเป็นต้องตระหนักถึงความคืบหน้าของงานอื่น เป็นไปได้ที่จะมีสิ่งเหล่านี้มากกว่าที่คุณจะสามารถทำงานพร้อมกันได้ พวกเขายังคงมีประโยชน์เพื่อความสะดวกแม้ว่าบางครั้งพวกเขาต้องรอแถวเรียงซ้อนกัน
ประเด็นก็คือแม้ว่าจะไม่ได้รับการเร่งความเร็วจริงใด ๆ เมื่อจำนวนเธรดเกินจำนวนหลักคุณสามารถใช้เธรดเพื่อแยกส่วนของตรรกะที่ไม่ควรพึ่งพาซึ่งกันและกัน
ในแอพพลิเคชั่นที่มีความซับซ้อนปานกลางการใช้เธรดเดียวพยายามทำทุกอย่างอย่างรวดเร็วทำให้แฮชของ 'flow' ของโค้ดของคุณ เธรดเดี่ยวใช้เวลาส่วนใหญ่ในการทำโพลนี้ตรวจสอบว่าเรียกรูทีนตามเงื่อนไขตามที่ต้องการและมันก็ยากที่จะเห็นสิ่งใดนอกเหนือจาก morut of minutiae
เปรียบเทียบสิ่งนี้กับเคสที่คุณสามารถอุทิศเธรดให้กับงานเพื่อให้คุณสามารถดูว่าเธรดใดทำงานอยู่ ตัวอย่างเช่นหนึ่งเธรดอาจบล็อกการรออินพุตจากซ็อกเก็ตแยกสตรีมเป็นข้อความข้อความกรองและเมื่อข้อความที่ถูกต้องมาพร้อมส่งผ่านไปยังเธรดผู้ปฏิบัติงานอื่น เธรดผู้ปฏิบัติงานสามารถทำงานกับอินพุตจากแหล่งอื่น ๆ รหัสสำหรับแต่ละรายการจะแสดงการไหลที่สะอาดและมีจุดประสงค์โดยไม่ต้องทำการตรวจสอบอย่างชัดเจนว่าไม่มีสิ่งอื่นใดให้ทำอีก
การแบ่งพาร์ติชันด้วยวิธีนี้ทำให้แอปพลิเคชันของคุณใช้ระบบปฏิบัติการเพื่อกำหนดเวลาว่าจะทำอย่างไรต่อไปกับซีพียูดังนั้นคุณไม่จำเป็นต้องตรวจสอบเงื่อนไขอย่างชัดเจนทุกที่ในแอปพลิเคชันของคุณเกี่ยวกับสิ่งที่อาจบล็อก
หากเธรดกำลังรอทรัพยากร (เช่นการโหลดค่าจาก RAM ลงในรีจิสเตอร์, ดิสก์ I / O, การเข้าถึงเครือข่าย, เปิดกระบวนการใหม่, ค้นหาฐานข้อมูลหรือรอการป้อนข้อมูลจากผู้ใช้) โปรเซสเซอร์สามารถทำงานบน เธรดที่แตกต่างกันและกลับไปที่เธรดแรกเมื่อทรัพยากรพร้อมใช้งาน สิ่งนี้จะช่วยลดเวลาที่ CPU ใช้งานโดยไม่ได้ใช้งานเนื่องจาก CPU สามารถดำเนินการหลายล้านการใช้งานแทนการไม่ได้ใช้งาน
พิจารณาเธรดที่ต้องการอ่านข้อมูลจากฮาร์ดไดรฟ์ ในปี 2014 แกนประมวลผลทั่วไปทำงานที่ 2.5 GHz และอาจดำเนินการ 4 คำสั่งต่อรอบ ด้วยรอบเวลา 0.4 ns โปรเซสเซอร์สามารถประมวลผล 10 คำสั่งต่อนาโนวินาที ด้วยฮาร์ดไดรฟ์แบบกลไกทั่วไปที่ใช้เวลาค้นหาประมาณ 10 มิลลิวินาทีโปรเซสเซอร์สามารถประมวลผลคำสั่งได้ 100 ล้านคำสั่งในเวลาที่อ่านค่าจากฮาร์ดไดรฟ์ อาจมีการปรับปรุงประสิทธิภาพอย่างมีนัยสำคัญกับฮาร์ดไดรฟ์ที่มีแคชขนาดเล็ก (บัฟเฟอร์ 4 MB) และไดรฟ์ไฮบริดที่มีพื้นที่เก็บข้อมูลไม่กี่ GB เนื่องจากเวลาแฝงข้อมูลสำหรับการอ่านหรืออ่านตามลำดับจากส่วนไฮบริด
แกนประมวลผลสามารถสลับไปมาระหว่างเธรด (ค่าใช้จ่ายสำหรับการหยุดชั่วคราวและดำเนินการต่อเธรดอยู่ที่ประมาณ 100 รอบนาฬิกา) ในขณะที่เธรดแรกรออินพุต latency สูง (มีราคาแพงกว่ารีจิสเตอร์ (1 นาฬิกา) และ RAM (5 นาโนวินาที)) disk I / O, การเข้าถึงเครือข่าย (เวลาแฝงของ 250ms), การอ่านข้อมูลจากซีดีหรือบัสช้าหรือการโทรฐานข้อมูล การมีเธรดมากกว่าคอร์หมายความว่าสามารถทำงานที่มีประโยชน์ได้ในขณะที่งานที่มีความหน่วงสูงได้รับการแก้ไข
CPU มีตัวกำหนดตารางเวลาเธรดที่กำหนดระดับความสำคัญให้กับแต่ละเธรดและอนุญาตให้เธรดเข้าสู่โหมดสลีปจากนั้นดำเนินการต่อหลังจากเวลาที่กำหนดไว้ล่วงหน้า มันเป็นงานของตัวจัดตารางเวลาเธรดเพื่อลด thrashing ซึ่งจะเกิดขึ้นหากแต่ละเธรดดำเนินการเพียง 100 คำสั่งก่อนที่จะถูกนำไปนอนอีกครั้ง โอเวอร์เฮดของสวิตชิ่งเธรดจะลดทรูพุตที่เป็นประโยชน์ทั้งหมดของตัวประมวลผลหลัก
ด้วยเหตุนี้คุณอาจต้องการแยกแยะปัญหาของคุณเป็นจำนวนเธรดที่สมเหตุสมผล ถ้าคุณเขียนโค้ดเพื่อดำเนินการคูณเมทริกซ์, การสร้างหนึ่งหัวข้อต่อเซลล์ในเมทริกซ์การส่งออกอาจจะมากเกินไปในขณะที่หนึ่งหัวข้อต่อแถวหรือต่อnแถวในเมทริกซ์ผลผลิตอาจลดต้นทุนค่าใช้จ่ายในการสร้างการหยุดและกลับมาทำงานหัวข้อ
นี่คือเหตุผลที่การทำนายสาขามีความสำคัญ หากคุณมีคำสั่ง if ที่ต้องการโหลดค่าจาก RAM แต่เนื้อความของคำสั่ง if และ else ใช้ค่าที่โหลดไว้ในรีจิสเตอร์โปรเซสเซอร์อาจประมวลผลหนึ่งหรือทั้งสองสาขาก่อนที่จะประเมินเงื่อนไข เมื่อเงื่อนไขส่งคืนตัวประมวลผลจะใช้ผลลัพธ์ของสาขาที่เกี่ยวข้องและยกเลิกอีกฝ่าย การทำงานที่ไร้ประโยชน์ที่นี่อาจจะดีกว่าการเปลี่ยนไปใช้เธรดอื่นซึ่งอาจนำไปสู่การฟาดฟัน
ในขณะที่เราย้ายออกจากตัวประมวลผลแบบ single-core ความเร็วสูงสัญญาณนาฬิกาไปยังตัวประมวลผลแบบ multi-core การออกแบบชิปได้เน้นที่การอัดแกนเพิ่มเติมต่อตายปรับปรุงการแบ่งปันทรัพยากรบนชิประหว่างแกนประมวลผลการทำนายสาขาที่ดีขึ้น และการตั้งเวลาเธรดที่ดีขึ้น
คำตอบส่วนใหญ่พูดถึงประสิทธิภาพและการทำงานพร้อมกัน ฉันจะเข้าใกล้สิ่งนี้จากมุมที่แตกต่าง
ลองพิจารณากรณีของโปรแกรมจำลองเทอร์มินัลอย่างง่าย คุณต้องทำสิ่งต่อไปนี้:
(ตัวจำลองเทอร์มินัลจริงทำอะไรได้มากกว่ารวมถึงการสะท้อนสิ่งที่คุณพิมพ์ลงบนจอแสดงผลเช่นกัน แต่เราจะผ่านสิ่งนั้นไปในตอนนี้)
ตอนนี้การวนลูปสำหรับการอ่านจากรีโมตนั้นเป็นเรื่องง่าย
while get-character-from-remote:
print-to-screen character
การวนลูปสำหรับการตรวจสอบคีย์บอร์ดและการส่งนั้นง่ายมาก:
while get-character-from-keyboard:
send-to-remote character
อย่างไรก็ตามปัญหาคือคุณต้องทำพร้อมกัน ตอนนี้โค้ดต้องมีลักษณะเช่นนี้มากขึ้นถ้าคุณไม่มีเกลียว:
loop:
check-for-remote-character
if remote-character-is-ready:
print-to-screen character
check-for-keyboard-entry
if keyboard-is-ready:
send-to-remote character
ตรรกะแม้ในตัวอย่างที่เข้าใจง่ายนี้ซึ่งไม่ได้คำนึงถึงความซับซ้อนของการสื่อสารในโลกแห่งความเป็นจริงนั้นค่อนข้างสับสน อย่างไรก็ตามเมื่อใช้เธรดแม้บนแกนเดียวลูป pseudocode ทั้งสองสามารถดำรงอยู่ได้อย่างอิสระโดยไม่ต้องพัวพันกับตรรกะของมัน เนื่องจากทั้งสองเธรดส่วนใหญ่จะเป็น I / O-bound จึงไม่ใส่ภาระหนักบน CPU แม้ว่าจะพูดอย่างเคร่งครัดและสิ้นเปลืองทรัพยากรของ CPU มากกว่าที่จะเป็นวงในตัว
แน่นอนว่าการใช้งานในโลกแห่งความเป็นจริงนั้นซับซ้อนกว่าข้างต้น แต่ความซับซ้อนของการวนซ้ำในตัวจะเพิ่มขึ้นเป็นทวีคูณเมื่อคุณเพิ่มความกังวลให้กับแอปพลิเคชันมากขึ้น ตรรกะได้รับการแยกส่วนมากขึ้นและคุณต้องเริ่มใช้เทคนิคเช่นเครื่องรัฐ, coroutines, et al เพื่อให้ได้สิ่งที่จัดการได้ จัดการได้ แต่อ่านไม่ได้ เธรดทำให้โค้ดอ่านได้ง่ายขึ้น
แล้วทำไมคุณไม่ใช้เกลียว?
ถ้างานของคุณเป็น CPU-bound แทนที่จะเป็น I / O-bound การทำเกลียวจะทำให้ระบบช้าลง ประสิทธิภาพจะแย่ลง มากในหลาย ๆ กรณี ("การฟาดฟัน" เป็นปัญหาที่พบโดยทั่วไปถ้าคุณปล่อยเธรดที่ผูกกับ CPU มากเกินไปคุณต้องใช้เวลามากขึ้นในการเปลี่ยนเธรดที่ใช้งานมากกว่าที่คุณรันเนื้อหาของเธรดเอง) นอกจากนี้หนึ่งในเหตุผลที่ตรรกะด้านบนคือ ง่ายมากคือฉันเลือกตัวอย่างแบบง่าย ๆ (และไม่สมจริง) อย่างจงใจ หากคุณต้องการสะท้อนสิ่งที่พิมพ์ลงบนหน้าจอคุณจะมีโลกใหม่ของความเจ็บปวดเมื่อคุณแนะนำการล็อคแหล่งข้อมูลที่ใช้ร่วมกัน ด้วยทรัพยากรที่ใช้ร่วมกันเพียงแหล่งเดียวมันไม่ได้เป็นปัญหามากนัก แต่มันก็เริ่มกลายเป็นปัญหาที่ใหญ่ขึ้นและใหญ่ขึ้นเมื่อคุณมีทรัพยากรที่จะแบ่งปันมากขึ้น
ดังนั้นในที่สุดการทำเกลียวก็เกี่ยวกับหลายสิ่งหลายอย่าง ตัวอย่างเช่นมันเกี่ยวกับการทำให้ I / O-bound กระบวนการตอบสนองมากขึ้น (แม้ว่าโดยรวมจะมีประสิทธิภาพน้อยลง) ตามที่บางคนกล่าวไว้แล้ว นอกจากนี้ยังเกี่ยวกับการทำให้ตรรกะง่ายต่อการติดตาม (แต่เฉพาะในกรณีที่คุณลดสถานะการแบ่งปันให้เหลือน้อยที่สุด) มันเกี่ยวกับสิ่งต่าง ๆ มากมายและคุณต้องตัดสินใจว่าข้อดีของมันมีมากกว่าข้อเสียของมันเป็นกรณี ๆ ไปหรือไม่
แม้ว่าคุณจะสามารถใช้เธรดเพื่อเร่งการคำนวณได้อย่างแน่นอนทั้งนี้ขึ้นอยู่กับฮาร์ดแวร์ของคุณ แต่หนึ่งในการใช้งานหลักของพวกเขาคือการทำมากกว่าหนึ่งสิ่งต่อครั้งด้วยเหตุผลที่เป็นมิตรกับผู้ใช้
ตัวอย่างเช่นหากคุณต้องทำการประมวลผลบางอย่างในพื้นหลังและยังคงตอบสนองต่ออินพุต UI คุณสามารถใช้เธรด หากไม่มีเธรดส่วนต่อประสานผู้ใช้จะหยุดทำงานทุกครั้งที่คุณพยายามทำการประมวลผลหนัก
ดูคำถามที่เกี่ยวข้องนี้ด้วย: การใช้งานจริงสำหรับเธรด
ฉันไม่เห็นด้วยอย่างยิ่งกับการยืนยันของ @ kyoryu ว่าตัวเลขในอุดมคติคือหนึ่งเธรดต่อ CPU
คิดแบบนี้: ทำไมเราถึงมีระบบปฏิบัติการหลายกระบวนการ? สำหรับประวัติคอมพิวเตอร์ส่วนใหญ่คอมพิวเตอร์เกือบทุกเครื่องมี CPU หนึ่งตัว แต่จากปี 1960 เป็นต้นไปคอมพิวเตอร์ "ของจริง" ทั้งหมดมีระบบปฏิบัติการหลายระบบ (หรือที่เรียกว่ามัลติทาสกิ้ง)
คุณเรียกใช้หลายโปรแกรมเพื่อให้สามารถเรียกใช้ในขณะที่คนอื่นถูกบล็อกสำหรับสิ่งต่าง ๆ เช่น IO
ให้กันข้อโต้แย้งว่า Windows รุ่นก่อน NT เป็นมัลติทาสกิ้งหรือไม่ ตั้งแต่นั้นมาทุกระบบปฏิบัติการจริงมีหลายงาน บางคนไม่เปิดเผยให้กับผู้ใช้ แต่มีอยู่แล้วทำสิ่งต่าง ๆ เช่นฟังวิทยุโทรศัพท์มือถือพูดคุยกับชิป GPS ยอมรับอินพุตเมาส์ ฯลฯ
เธรดเป็นเพียงงานที่มีประสิทธิภาพมากกว่านี้เล็กน้อย ไม่มีความแตกต่างพื้นฐานระหว่างงานกระบวนการและเธรด
ซีพียูเป็นสิ่งที่น่าขยะแขยงดังนั้นจึงมีหลายสิ่งให้ใช้เมื่อคุณสามารถทำได้
ฉันจะยอมรับว่าด้วยภาษาเชิงโพรซีเดอร์ส่วนใหญ่, C, C ++, Java ฯลฯ การเขียนโค้ดที่ปลอดภัยของเธรดที่เหมาะสมนั้นเป็นงานจำนวนมาก ด้วยซีพียู 6 คอร์ในตลาดวันนี้และซีพียู 16 คอร์อยู่ไม่ไกลฉันคาดหวังว่าผู้คนจะย้ายออกจากภาษาเก่าเหล่านี้เนื่องจากมัลติเธรดเป็นข้อกำหนดที่สำคัญยิ่งขึ้น
ความไม่ลงรอยกันกับ @kyoryu เป็นเพียง IMHO ส่วนที่เหลือคือข้อเท็จจริง
ลองนึกภาพเว็บเซิร์ฟเวอร์ที่ต้องให้บริการจำนวนคำขอโดยพลการ คุณต้องให้บริการคำขอแบบขนานเพราะมิฉะนั้นคำขอใหม่แต่ละคำขอจะต้องรอจนกว่าคำขออื่น ๆ ทั้งหมดจะเสร็จสมบูรณ์ (รวมถึงการส่งการตอบกลับทางอินเทอร์เน็ต) ในกรณีนี้เว็บเซิร์ฟเวอร์ส่วนใหญ่จะมีคอร์น้อยกว่าจำนวนคำขอที่พวกเขามักจะให้บริการ
นอกจากนี้ยังทำให้ผู้พัฒนาเซิร์ฟเวอร์ทำได้ง่ายขึ้น: คุณเพียง แต่ต้องเขียนโปรแกรมเธรดที่ให้บริการตามคำขอคุณไม่ต้องคิดเกี่ยวกับการเก็บคำขอหลายคำขอลำดับที่คุณให้บริการและอื่น ๆ
หลายเธรดจะนอนหลับกำลังรออินพุตผู้ใช้ I / O และเหตุการณ์อื่น ๆ
เธรดสามารถช่วยตอบสนองในแอปพลิเคชัน UI นอกจากนี้คุณสามารถใช้เธรดเพื่อทำงานให้คอร์ของคุณทำงานได้มากขึ้น ตัวอย่างเช่นในแกนเดียวคุณสามารถมีหนึ่งเธรดที่ทำ IO และอีกอันหนึ่งทำการคำนวณ ถ้าเป็นเธรดเดี่ยวแกนหลักอาจไม่มีการใช้งานเพื่อรอ IO ให้เสร็จสมบูรณ์ นั่นเป็นตัวอย่างระดับสูง แต่สามารถใช้เธรดเพื่อทำให้ CPU ของคุณหนักขึ้นได้
ตัวประมวลผลหรือ CPU คือชิปแบบฟิสิคัลที่เสียบเข้ากับระบบ โปรเซสเซอร์สามารถมีหลายคอร์ (แกนเป็นส่วนหนึ่งของชิปที่มีความสามารถในการดำเนินการคำสั่ง) แกนประมวลผลอาจปรากฏต่อระบบปฏิบัติการเป็นตัวประมวลผลเสมือนหลายตัวหากสามารถประมวลผลหลายเธรดได้พร้อมกัน (เธรดเป็นชุดคำสั่งเดียว)
กระบวนการเป็นอีกชื่อหนึ่งของแอปพลิเคชัน โดยทั่วไปกระบวนการเป็นอิสระจากกัน หากกระบวนการหนึ่งตายมันไม่ทำให้กระบวนการอื่นตายเช่นกัน เป็นไปได้สำหรับกระบวนการในการสื่อสารหรือแบ่งปันทรัพยากรเช่นหน่วยความจำหรือ I / O
แต่ละกระบวนการมีพื้นที่ที่อยู่และสแต็คแยกต่างหาก กระบวนการสามารถมีหลายกระทู้แต่ละคนสามารถดำเนินการตามคำสั่งพร้อมกัน เธรดทั้งหมดในกระบวนการแชร์พื้นที่ที่อยู่เดียวกัน แต่แต่ละเธรดจะมีสแต็กของตัวเอง
หวังว่าด้วยคำจำกัดความเหล่านี้และการวิจัยเพิ่มเติมโดยใช้พื้นฐานเหล่านี้จะช่วยให้คุณเข้าใจ
การใช้เธรดในอุดมคตินั้นแท้จริงแล้วต่อหนึ่งคอร์
อย่างไรก็ตามถ้าคุณใช้ IO แบบอะซิงโครนัส / ไม่ใช่การปิดกั้นโดยเฉพาะมีโอกาสที่คุณจะมีเธรดที่ถูกบล็อกบน IO ในบางจุดซึ่งจะไม่ใช้ CPU ของคุณ
นอกจากนี้ภาษาการเขียนโปรแกรมทั่วไปทำให้การใช้ 1 เธรดต่อ CPU ค่อนข้างยาก ภาษาที่ออกแบบมาพร้อมกัน (เช่น Erlang) สามารถช่วยให้ไม่ใช้หัวข้อเพิ่มเติมได้ง่ายขึ้น
วิธีที่ API บางตัวได้รับการออกแบบคุณไม่มีทางเลือกนอกจากให้รันในเธรดแยกต่างหาก (ทุกสิ่งที่มีการบล็อกการดำเนินงาน) ตัวอย่างจะเป็นไลบรารี HTTP ของ Python (AFAIK)
ปกติแล้วนี่ไม่ใช่ปัญหามากนัก (หากเป็นปัญหา OS หรือ API ควรมาพร้อมกับโหมดการทำงานแบบอะซิงโครนัสทางเลือกเช่น:) select(2)
เนื่องจากอาจเป็นไปได้ว่าเธรดกำลังจะหลับระหว่างรอ I / เสร็จสิ้น ในทางกลับกันหากมีบางสิ่งที่กำลังทำการคำนวณอย่างหนักคุณต้องใส่ไว้ในเธรดแยกต่างหากนอกเหนือจากการพูดเธรด GUI (เว้นแต่คุณจะเพลิดเพลินกับการทำมัลติเพล็กซ์ด้วยตนเอง)
ฉันรู้ว่านี่เป็นคำถามเก่าแก่ที่มีคำตอบที่ดีมากมาย แต่ฉันมาที่นี่เพื่อชี้ให้เห็นสิ่งที่สำคัญในสภาพแวดล้อมปัจจุบัน:
หากคุณต้องการออกแบบแอพพลิเคชั่นสำหรับมัลติเธรดคุณไม่ควรออกแบบสำหรับการตั้งค่าฮาร์ดแวร์เฉพาะ เทคโนโลยีซีพียูได้รับความก้าวหน้าอย่างรวดเร็วมาหลายปีและจำนวนคอร์นับเพิ่มขึ้นอย่างต่อเนื่อง หากคุณตั้งใจออกแบบแอปพลิเคชันของคุณโดยใช้เพียง 4 เธรดคุณอาจ จำกัด ตัวเองในระบบ octa-core (เช่น) ตอนนี้แม้แต่ระบบ 20 คอร์ก็ยังมีวางจำหน่ายทั่วไปดังนั้นการออกแบบดังกล่าวย่อมทำอันตรายมากกว่าดี
ในการตอบสนองต่อการคาดเดาครั้งแรกของคุณ: เครื่องมัลติคอร์สามารถเรียกใช้หลายกระบวนการพร้อมกันไม่ใช่แค่หลายเธรดของกระบวนการเดียว
ในการตอบคำถามแรกของคุณ: จุดของหลายเธรดมักจะทำงานหลายอย่างพร้อมกันภายในแอปพลิเคชันเดียว ตัวอย่างคลาสสิกบนเน็ตคือโปรแกรมอีเมลที่ส่งและรับจดหมายและเว็บเซิร์ฟเวอร์ที่รับและส่งคำขอหน้าเว็บ (โปรดทราบว่าเป็นไปไม่ได้ที่จะลดระบบเช่น Windows ให้ทำงานเพียงหนึ่งเธรดหรือแม้แต่เพียงกระบวนการเดียว) ให้เรียกใช้ตัวจัดการงานของ Windows และโดยทั่วไปคุณจะเห็นรายการที่ยาวนานของกระบวนการที่ใช้งานอยู่ )
เพื่อตอบคำถามที่สองของคุณ: กระบวนการ / เธรดส่วนใหญ่ไม่ได้เชื่อมโยงกับ CPU (เช่นไม่ทำงานอย่างต่อเนื่องและไม่หยุดชะงัก) แต่ให้หยุดและรอบ่อยๆเพื่อให้ I / O เสร็จสิ้น ในระหว่างการรอนั้นกระบวนการ / เธรดอื่นสามารถทำงานได้โดยไม่ต้อง "ขโมย" จากรหัสที่รอ (แม้ในเครื่องแกนเดียว)
เธรดเป็นนามธรรมที่ช่วยให้คุณสามารถเขียนโค้ดได้ง่ายเหมือนลำดับของการดำเนินการโดยไม่รู้ตัวว่าโค้ดนั้นถูกดำเนินการแบบ interlaced กับโค้ดอื่นหรือจอดรอ IO หรือ (อาจจะค่อนข้างรู้มากกว่า) รอเธรดอื่น เหตุการณ์หรือข้อความ
ประเด็นก็คือโปรแกรมเมอร์ส่วนใหญ่ไม่เข้าใจวิธีการออกแบบเครื่องของรัฐ ความสามารถในการใส่ทุกอย่างลงในเธรดของตนเองทำให้โปรแกรมเมอร์ไม่ต้องคิดเกี่ยวกับวิธีการแสดงสถานะของการคำนวณที่กำลังดำเนินการต่าง ๆ อย่างมีประสิทธิภาพเพื่อให้พวกเขาสามารถถูกขัดจังหวะและกลับมาทำงานในภายหลังได้
ยกตัวอย่างเช่นพิจารณาการบีบอัดวิดีโอซึ่งเป็นงานที่ใช้ cpu มาก หากคุณใช้เครื่องมือ gui คุณอาจต้องการให้อินเทอร์เฟซยังคงตอบสนอง (แสดงความคืบหน้าตอบสนองต่อการร้องขอที่ยกเลิกการปรับขนาดหน้าต่าง ฯลฯ ) ดังนั้นคุณจึงออกแบบซอฟต์แวร์เข้ารหัสของคุณเพื่อประมวลผลหน่วยขนาดใหญ่ (หนึ่งเฟรมขึ้นไป) ในแต่ละครั้งและเรียกใช้ในเธรดของตัวเองแยกต่างหากจาก UI
แน่นอนว่าเมื่อคุณรู้แล้วว่าเป็นการดีที่จะสามารถบันทึกสถานะการเข้ารหัสที่กำลังดำเนินอยู่เพื่อให้คุณสามารถปิดโปรแกรมเพื่อเริ่มระบบใหม่หรือเล่นเกมที่ต้องใช้ทรัพยากรคุณรู้ว่าคุณควรได้เรียนรู้วิธีการออกแบบเครื่องรัฐจาก จุดเริ่มต้น ไม่ว่าจะเป็นหรือคุณตัดสินใจที่จะสร้างปัญหาใหม่ของการจำศีลในระบบปฏิบัติการของคุณเพื่อให้คุณสามารถระงับและดำเนินการแอปแต่ละตัวต่อไปยังดิสก์ ...