coroutine คืออะไร พวกเขาเกี่ยวข้องกับการเกิดพร้อมกันอย่างไร?
coroutine คืออะไร พวกเขาเกี่ยวข้องกับการเกิดพร้อมกันอย่างไร?
คำตอบ:
Coroutines และภาวะพร้อมกันส่วนใหญ่จะตั้งฉาก Coroutines เป็นโครงสร้างการควบคุมทั่วไปโดยการควบคุมการไหลจะถูกส่งผ่านระหว่างสองรูทีนที่ต่างกันโดยไม่ส่งคืน
คำสั่ง 'yield' ใน Python เป็นตัวอย่างที่ดี มันสร้าง coroutine เมื่อ 'ผลผลิต' พบสถานะปัจจุบันของฟังก์ชั่นจะถูกบันทึกและการควบคุมจะถูกส่งกลับไปยังฟังก์ชั่นการโทร ฟังก์ชั่นการโทรสามารถโอนการดำเนินการกลับไปที่ฟังก์ชันการให้ผลตอบแทนและสถานะของมันจะถูกเรียกคืนไปยังจุดที่พบ 'ผลผลิต' และการดำเนินการจะดำเนินต่อไป
Coroutines are a general control structure whereby flow control is cooperatively passed between two different routines without returning.
<- นี่คือการทำงานพร้อมกัน คำที่คุณต้องการคือความเท่าเทียม
orthogonal = Not similar to each other
?
orthogonal
หมายความว่า "เป็นอิสระจากกัน"
จากการเขียนโปรแกรมใน Lua " Coroutines
" ส่วน:
Coroutine นั้นคล้ายกับเธรด (ในแง่ของการทำงานแบบมัลติเธรด): มันเป็นบรรทัดของการประมวลผลโดยมีสแต็กของตัวเองตัวแปรท้องถิ่นของมันเองและตัวชี้คำสั่งของมันเอง แต่มันก็แบ่งปันตัวแปรทั่วโลกและส่วนใหญ่เป็นอย่างอื่นกับ coroutines อื่น ๆ ความแตกต่างที่สำคัญระหว่างเธรดและ coroutines คือแนวคิด (หรือตัวอักษรในเครื่องมัลติโปรเซสเซอร์) โปรแกรมที่มีเธรดรันหลายเธรดพร้อมกัน ในทางกลับกัน Coroutines จะทำงานร่วมกัน: ในเวลาใดก็ตามโปรแกรมที่มี coroutines กำลังทำงานเพียงหนึ่งใน coroutines ของมันและ coroutine ที่ทำงานอยู่นี้จะหยุดการทำงานของมันเฉพาะเมื่อมันร้องขออย่างชัดเจนที่จะถูกระงับ
ดังนั้นประเด็นคือ: Coroutines คือ "การทำงานร่วมกัน" แม้ในระบบ multi-core มีเพียง coroutine เดียวที่ทำงานในเวลาที่กำหนด (แต่หลายเธรดสามารถทำงานแบบขนาน) ไม่มีการยึดเอาเสียก่อนระหว่าง coroutines, coroutine ที่กำลังทำงานอยู่จะต้องยกเลิกการดำเนินการอย่างชัดเจน
สำหรับ " concurrency
" คุณสามารถดูสไลด์ของ Rob Pike ได้:
การเกิดขึ้นพร้อมกันคือองค์ประกอบของการคำนวณแบบอิสระ
ดังนั้นในระหว่างการดำเนิน coroutine เอมันผ่านการควบคุมไป B. coroutine แล้วหลังจากที่บางครั้ง coroutine B ผ่านการควบคุมกลับไป coroutine A. เนื่องจากมีการพึ่งพาระหว่าง coroutines และพวกเขาจะต้องทำงานควบคู่ดังนั้นทั้งสอง coroutines มีความไม่เห็นพ้องด้วย
ฉันค้นหาคำตอบส่วนใหญ่ทางเทคนิคด้วยแม้ว่ามันจะเป็นคำถามทางเทคนิค ฉันมีเวลายากที่จะเข้าใจกระบวนการ coroutine ฉันเข้าใจแล้ว แต่ฉันก็ไม่เข้าใจในเวลาเดียวกัน
ฉันพบคำตอบนี้ที่นี่มีประโยชน์มาก:
https://dev.to/thibmaek/explain-coroutines-like-im-five-2d9
อ้างจาก Idan Arye:
เพื่อสร้างเรื่องราวของคุณฉันจะใส่มันในลักษณะนี้:
คุณเริ่มดูการ์ตูน แต่มันเป็นบทนำ แทนที่จะดูอินโทรคุณเปลี่ยนไปเล่นเกมและเข้าสู่ล็อบบี้ออนไลน์ - แต่มันต้องการผู้เล่น 3 คนและมีคุณและน้องสาวของคุณอยู่ในนั้น แทนที่จะรอให้ผู้เล่นคนอื่นเข้าร่วมคุณเปลี่ยนไปทำการบ้านและตอบคำถามแรก คำถามที่สองมีลิงก์ไปยังวิดีโอ YouTube ที่คุณต้องดู คุณเปิดมันและมันก็เริ่มโหลด แทนที่จะรอให้โหลดคุณสลับกลับไปที่การ์ตูน คำนำจบลงแล้วเพื่อให้คุณดูได้ ขณะนี้มีโฆษณา - แต่ในขณะที่ผู้เล่นคนที่สามได้เข้าร่วมดังนั้นคุณเปลี่ยนเป็นเกมและอื่น ๆ ...
แนวคิดคือคุณไม่เพียง แต่สลับงานอย่างรวดเร็วเพื่อให้ดูเหมือนว่าคุณกำลังทำทุกอย่างในครั้งเดียว คุณใช้เวลาที่คุณกำลังรอให้บางสิ่งเกิดขึ้น (IO) ทำสิ่งอื่น ๆ ที่ต้องการความสนใจโดยตรงของคุณ
ตรวจสอบการเชื่อมโยงแน่นอนมีอีกมากมายที่ฉันไม่สามารถพูดทุกอย่าง
Coroutine คล้ายกับรูทีนย่อย / เธรด ความแตกต่างคือเมื่อผู้เรียกใช้เรียกรูทีนย่อย / เธรดมันจะไม่ย้อนกลับไปที่ฟังก์ชันผู้เรียก แต่ coroutine สามารถกลับไปที่ caller หลังจากรันโค้ดสองสามชิ้นเพื่อให้ผู้เรียกใช้รันโค้ดบางส่วนของมันเองและกลับไปยังจุด coroutine ที่มันหยุดการทำงานและดำเนินการต่อจากที่นั่น กล่าวคือ Coroutine มีมากกว่าหนึ่งจุดเข้าและออก
โดยทั่วไปมีสองประเภทของ Coroutines:
Kotlin ใช้ coroutines แบบไม่มีสแต็ก - หมายความว่า coroutines ไม่มีสแต็กของตัวเองดังนั้นมันจึงไม่จับคู่กับเธรดดั้งเดิม
นี่เป็นฟังก์ชั่นในการเริ่มต้น coroutine:
launch{}
async{}
คุณสามารถเรียนรู้เพิ่มเติมได้จากที่นี่:
https://www.kotlindevelopment.com/deep-dive-coroutines/
https://blog.mindorks.com/what-are-coroutines-in-kotlin-bf4fecd476e9
เมื่อทราบที่แตกต่างกันในหลามgevent
ห้องสมุดเป็นcoroutine
ห้องสมุดเครือข่ายตามที่ช่วยให้คุณเส้นด้ายคุณสมบัติเช่นร้องขอของเครือข่าย async โดยไม่มีค่าใช้จ่ายในการสร้างและทำลายหัวข้อ ห้องสมุดใช้coroutine
greenlet
จากPython Coroutine :
การดำเนินการของ Python coroutines สามารถหยุดชั่วคราวและดำเนินการต่อในหลาย ๆ จุด (ดู coroutine) ภายในเนื้อหาของฟังก์ชัน coroutine การรอคอยและตัวระบุ async กลายเป็นคำหลักที่สงวนไว้ รอการแสดงออก async สำหรับและ async กับสามารถใช้ในร่างกายฟังก์ชั่น coroutine
coroutine เป็นฟังก์ชั่นที่สามารถระงับการดำเนินการที่จะกลับมา ในภายหลัง Coroutines ไม่มีวางซ้อน: พวกมันจะหยุดการประมวลผลโดยกลับไปที่ผู้โทร สิ่งนี้อนุญาตให้ใช้รหัสลำดับที่ดำเนินการแบบอะซิงโครนัส (เช่นจัดการกับ I / O ที่ไม่มีการบล็อกโดยไม่มีการเรียกกลับที่ชัดเจน) และสนับสนุนอัลกอริทึมสำหรับลำดับอนันต์ที่คำนวณได้ขี้เกียจและการใช้อื่น ๆ
เปรียบเทียบกับคำตอบของคนอื่น:
ในความคิดของฉันชิ้นส่วนที่กลับมาทำงานต่อเป็นความแตกต่างหลักเช่นเดียวกับ @ Twinkle
แม้ว่าเอกสารจำนวนมากยังคงอยู่ระหว่างดำเนินการ แต่ส่วนนี้คล้ายกับคำตอบส่วนใหญ่ยกเว้น @Nan Xiao
ในทางกลับกัน Coroutines ทำงานร่วมกัน: ในเวลาใดก็ตามโปรแกรมที่มี coroutines กำลังทำงานเพียงหนึ่งใน coroutines ของมันและ coroutine ที่กำลังทำงานอยู่นี้จะหยุดการทำงานเฉพาะเมื่อมีการร้องขอที่จะถูกระงับอย่างชัดเจน
เนื่องจากมันอ้างจากโปรแกรมใน Lua อาจเกี่ยวข้องกับภาษา (ไม่คุ้นเคยกับ Lua ในปัจจุบัน) ไม่ใช่เอกสารทั้งหมดที่กล่าวถึงเพียงส่วนเดียว
ความสัมพันธ์ที่เกิดขึ้นพร้อมกัน:
มีส่วน "การดำเนินการ" ของCoroutines (C ++ 20)ใช้เวลานานในการอ้างอิงที่นี่
นอกจากรายละเอียดแล้วยังมีอีกหลายรัฐ
When a coroutine begins execution
When a coroutine reaches a suspension point
When a coroutine reaches the co_return statement
If the coroutine ends with an uncaught exception
When the coroutine state is destroyed either because it terminated via co_return or uncaught exception, or because it was destroyed via its handle
เป็นความคิดเห็นจาก @Adam Arold ภายใต้คำตอบของ @ user217714 มันเห็นพ้องด้วย
แต่มันแตกต่างจากมัลติเธรด
จาก std :: ด้าย
เธรดอนุญาตให้ใช้งานได้หลายฟังก์ชั่นพร้อมกัน เธรดจะเริ่มดำเนินการทันทีเมื่อสร้างวัตถุเธรดที่เกี่ยวข้อง (รอการหน่วงเวลาการตั้งเวลาระบบปฏิบัติการใด ๆ ) โดยเริ่มจากฟังก์ชั่นระดับบนสุดที่ให้ไว้เป็นอาร์กิวเมนต์ตัวสร้าง ค่าตอบแทนของฟังก์ชั่นระดับบนสุดจะถูกละเว้นและถ้ามันยุติโดยการโยนข้อยกเว้น std :: terminate จะถูกเรียก ฟังก์ชั่นระดับบนสุดอาจสื่อสารค่าที่ส่งคืนหรือข้อยกเว้นไปยังผู้เรียกผ่าน std :: contract หรือโดยการปรับเปลี่ยนตัวแปรที่แชร์ (ซึ่งอาจต้องการการซิงโครไนซ์ดู std :: mutex และ std :: atomic)
เนื่องจากมันเกิดขึ้นพร้อมกันมันทำงานเหมือนมัลติเธรดโดยเฉพาะอย่างยิ่งเมื่อการรอไม่สามารถหลีกเลี่ยงได้ (จากมุมมองของระบบปฏิบัติการ) นั่นเป็นสาเหตุที่ทำให้เกิดความสับสน
Coroutine เป็นโปรแกรมย่อยชนิดพิเศษ แทนที่จะเป็นความสัมพันธ์หลักระหว่างผู้เรียกและโปรแกรมย่อยที่เรียกว่าที่มีอยู่กับโปรแกรมย่อยทั่วไปผู้โทรและ coroutines จะมีความเท่าเทียมกันมากกว่า
Coroutine เป็นโปรแกรมย่อยที่มีหลายรายการและควบคุมพวกมันเอง - รองรับโดยตรงใน Lua
เรียกอีกอย่างว่าการควบคุมแบบสมมาตร: ผู้โทรและเรียกว่า coroutines อยู่บนพื้นฐานที่เท่าเทียมกันมากขึ้น
การเรียก coroutine มีชื่อว่า Resume
ประวัติย่อครั้งแรกของ coroutine คือการเริ่มต้น แต่การโทรที่ตามมาจะเข้าสู่จุดหลังจากคำสั่งที่ดำเนินการครั้งสุดท้ายใน coroutine
Coroutines กลับมาทำงานกันอย่างต่อเนื่อง
Coroutines จัดเตรียมการใช้งานโปรแกรมพร้อมกันแบบเสมือนพร้อมกัน (coroutines); การดำเนินการของพวกเขาคือ interleaved แต่ไม่ทับซ้อนกัน
ฉันพบว่าคำอธิบายจากลิงค์นี้ค่อนข้างตรงไปตรงมา ไม่มีคำตอบใดที่พยายามอธิบายการเกิดพร้อมกันเทียบได้พร้อมกันยกเว้นสัญลักษณ์แสดงหัวข้อย่อยสุดท้ายในคำตอบนี้
อ้างจาก "การเขียนโปรแกรม Erlang" โดยโจอาร์มสตรองตำนาน:
โปรแกรมที่ทำงานพร้อมกันสามารถทำงานได้เร็วขึ้นบนคอมพิวเตอร์แบบขนาน
โปรแกรมที่ทำงานพร้อมกันคือโปรแกรมที่เขียนด้วยภาษาโปรแกรมที่เกิดขึ้นพร้อมกัน เราเขียนโปรแกรมที่เกิดขึ้นพร้อมกันเพื่อเหตุผลด้านประสิทธิภาพความสามารถในการปรับขนาดหรือความทนทานต่อข้อบกพร่อง
ภาษาโปรแกรมที่เกิดขึ้นพร้อมกันคือภาษาที่มีภาษาที่สร้างขึ้นอย่างชัดเจนสำหรับการเขียนโปรแกรมที่เกิดขึ้นพร้อมกัน โครงสร้างเหล่านี้เป็นส่วนสำคัญของภาษาโปรแกรมและทำงานในลักษณะเดียวกันกับทุกระบบปฏิบัติการ
คอมพิวเตอร์คู่ขนานคือคอมพิวเตอร์ที่มีหน่วยประมวลผลหลายตัว (CPU หรือแกนประมวลผล) ที่สามารถทำงานได้ในเวลาเดียวกัน
ดังนั้นการเห็นพ้องด้วยกันจึงไม่เหมือนกับการขนาน คุณยังสามารถเขียนโปรแกรมที่ทำงานพร้อมกันบนคอมพิวเตอร์แบบแกนเดียว ตัวกำหนดเวลาการแชร์เวลาจะทำให้คุณรู้สึกว่าโปรแกรมของคุณทำงานพร้อมกัน
โปรแกรมพร้อมกันมีศักยภาพในการทำงานแบบขนานในคอมพิวเตอร์ขนาน แต่ไม่รับประกัน ระบบปฏิบัติการอาจให้แกนเดียวแก่คุณเพื่อเรียกใช้โปรแกรมของคุณ
ดังนั้นการทำงานพร้อมกันเป็นรูปแบบซอฟต์แวร์จากโปรแกรมที่เกิดขึ้นพร้อมกันซึ่งไม่ได้หมายความว่าโปรแกรมของคุณสามารถทำงานแบบขนานได้
คำว่า "coroutine" ประกอบด้วยสองคำ: "co" (สหกรณ์) และ "กิจวัตร" (ฟังก์ชั่น)
มันบรรลุพร้อมกันหรือขนาน?
เพื่อให้ง่ายเรามาพูดคุยกันในคอมพิวเตอร์แบบแกนเดียว
เกิดขึ้นพร้อมกันโดยใช้เวลาร่วมกันจากระบบปฏิบัติการ เธรดดำเนินการรหัสในกรอบเวลาที่กำหนดบนแกน CPU มันสามารถจองได้โดยระบบปฏิบัติการ นอกจากนี้ยังอาจให้การควบคุมระบบปฏิบัติการ
ในทางกลับกัน coroutine จะให้การควบคุมกับ coroutine อื่นภายในเธรดไม่ใช่ไปที่ OS ดังนั้น coroutines ทั้งหมดภายในเธรดยังคงใช้ประโยชน์จากกรอบเวลาสำหรับเธรดนั้นโดยไม่ยอมให้ CPU core กับเธรดอื่นที่จัดการโดย OS
ดังนั้นคุณสามารถคิดได้ว่าcoroutine จะได้รับการแบ่งปันเวลาโดยผู้ใช้ที่ไม่ได้มาจากระบบปฏิบัติการ (หรือแบบกึ่งขนาน) Coroutines ทำงานบนแกนเดียวกันที่กำหนดให้กับเธรดที่รัน coroutines เหล่านั้น
Coroutine บรรลุขนานหรือไม่ หากเป็นรหัสที่ผูกกับ CPU อยู่ เช่นเดียวกับเวลาที่ใช้ร่วมกันมันทำให้คุณรู้สึกว่ามันวิ่งขนานกัน แต่การประหารชีวิตของพวกเขานั้นไม่ได้ซ้อนทับกัน ถ้ามันถูกผูกไว้กับ IO ใช่มันจะได้รับขนานโดยฮาร์ดแวร์ (อุปกรณ์ IO) ไม่ใช่โดยรหัสของคุณ
ข ความแตกต่างกับการเรียกฟังก์ชั่นคืออะไร?
ดังรูปที่แสดงมันไม่จำเป็นต้องเรียกreturn
เพื่อสลับการควบคุม return
มันสามารถให้ผลผลิตได้โดยไม่ต้อง coroutine บันทึกและแบ่งปันสถานะของฟังก์ชั่นเฟรมปัจจุบัน (stack) call ret
ดังนั้นจึงเป็นมากขึ้นมีน้ำหนักเบากว่าฟังก์ชั่นเนื่องจากคุณไม่ต้องบันทึกลงทะเบียนและตัวแปรท้องถิ่นไปยังกองและสแต็คย้อนกลับสายเมื่อ
ฉันจะขยายคำตอบของ @ user21714 Coroutines เป็นเส้นทางการดำเนินการอิสระที่ไม่สามารถทำงานพร้อมกันได้ พวกมันขึ้นอยู่กับคอนโทรลเลอร์ - ตัวอย่างเช่นpython
ไลบรารีคอนโทรลเลอร์ - เพื่อจัดการการสลับระหว่างพา ธ เหล่านี้ แต่สำหรับสิ่งนี้ในการทำงาน coroutines ตัวเองต้องเรียกyield
หรือโครงสร้างที่คล้ายกันที่ช่วยให้การดำเนินการของพวกเขาจะหยุดชั่วคราว
เธรดกำลังรันบนทรัพยากรการคำนวณอิสระและขนานกัน เนื่องจากอยู่ในแหล่งข้อมูลที่แตกต่างกันจึงไม่จำเป็นต้องเรียกใช้อัตราผลตอบแทนเพื่ออนุญาตให้เส้นทางการดำเนินการอื่นดำเนินการต่อ
ท่านสามารถเข้าดูผลกระทบนี้ด้วยการเริ่มต้นโปรแกรม multihreaded - เช่นjvm
แอพลิเคชัน - ที่แปดของคุณcore i7
แกน hyperthread ถูกนำมาใช้: คุณอาจจะเห็นการใช้ 797% ในหรือActivity Monitor
Top
เมื่อเรียกใช้python
โปรแกรมทั่วไป- แม้แต่โปรแกรมที่มีcoroutines
หรือpython threading
- การใช้งานจะสูงสุดที่ 100% เช่นหนึ่งเครื่อง hyperthread