ทำไม coroutines ถึงกลับมา? [ปิด]


19

ส่วนใหญ่ของรากฐานสำหรับ coroutines เกิดขึ้นใน 60s / 70s แล้วหยุดในความโปรดปรานของทางเลือก (เช่นหัวข้อ)

มีสารใด ๆ ที่สนใจต่ออายุใน coroutines ที่เกิดขึ้นในหลามและภาษาอื่น ๆ ?



9
ฉันไม่แน่ใจว่าพวกเขาจะจากไป
Blrfl

คำตอบ:


26

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

หนึ่งในกระบวนทัศน์การเขียนโปรแกรมที่ใหญ่ที่สุดของ 80, 90 และวันนี้คือ OOP ถ้าเราดูประวัติของ OOP และพัฒนาภาษา Simula โดยเฉพาะเราจะเห็นว่าคลาสนั้นวิวัฒนาการมาจากภาษาคอรัล Simula มีไว้สำหรับการจำลองระบบที่มีเหตุการณ์ไม่ต่อเนื่อง แต่ละองค์ประกอบของระบบเป็นกระบวนการแยกต่างหากที่จะดำเนินการเพื่อตอบสนองต่อเหตุการณ์ในช่วงระยะเวลาหนึ่งขั้นตอนการจำลองจากนั้นให้ผลเพื่อให้กระบวนการอื่นทำงาน ในระหว่างการพัฒนา Simula 67 แนวคิดของชั้นเรียนได้ถูกนำเสนอ ตอนนี้สถานะถาวรของ coroutine จะถูกเก็บไว้ในสมาชิกวัตถุและเหตุการณ์จะถูกทริกเกอร์โดยการเรียกวิธีการ สำหรับรายละเอียดเพิ่มเติมลองอ่านบทความการพัฒนาภาษา SIMULAโดย Nygaard & Dahl

ดังนั้นในการบิดตลกที่เราใช้ coroutines ตลอดเราเพียงแค่เรียกพวกเขาวัตถุและการเขียนโปรแกรมขับเคลื่อนเหตุการณ์

สำหรับความเท่าเทียมนั้นมีสองภาษา: ภาษาที่มีรูปแบบหน่วยความจำที่เหมาะสมและภาษาที่ไม่มี แบบจำลองหน่วยความจำกล่าวถึงสิ่งต่าง ๆ เช่น "ถ้าฉันเขียนไปยังตัวแปรและหลังจากอ่านจากตัวแปรนั้นในเธรดอื่นฉันจะเห็นค่าเก่าหรือค่าใหม่หรืออาจเป็นค่าที่ไม่ถูกต้องหรือไม่? 'ก่อน' และ 'หลังจาก' หมายถึงอะไร การดำเนินการใดที่รับประกันว่าเป็นอะตอม”

การสร้างโมเดลหน่วยความจำที่ดีนั้นเป็นเรื่องยากดังนั้นความพยายามนี้จึงไม่เคยเกิดขึ้นสำหรับภาษาโอเพนซอร์สแบบไดนามิกที่ไม่ได้กำหนดและกำหนดใช้งานส่วนใหญ่: Perl, JavaScript, Python, Ruby, PHP แน่นอนว่าภาษาทั้งหมดเหล่านั้นพัฒนาไปไกลกว่า“ สคริปต์” ที่พวกเขาสร้างขึ้นมาเพื่อ ภาษาเหล่านี้บางภาษามีเอกสารโมเดลหน่วยความจำบางประเภท แต่ภาษาเหล่านั้นไม่เพียงพอ เรามีแฮ็กแทน:

  • Perl สามารถคอมไพล์ได้ด้วยการสนับสนุนเธรด แต่แต่ละเธรดมีการแยกสถานะการแปลที่สมบูรณ์ทำให้เธรดมีราคาแพง ในฐานะที่เป็นผลประโยชน์เพียงอย่างเดียววิธีการแบบไม่มีอะไรที่ใช้ร่วมกันนี้ช่วยหลีกเลี่ยงการแข่งขันของข้อมูลและบังคับให้โปรแกรมเมอร์สื่อสารผ่านคิว / สัญญาณ / IPC เท่านั้น Perl ไม่มีเรื่องราวที่แข็งแกร่งสำหรับการประมวลผลแบบ async

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

  • Python มีคุณสมบัติที่โชคร้ายที่เรียกว่า Global Interpreter Lock โดยทั่วไปโมเดลหน่วยความจำของ Python คือ“ เอฟเฟกต์ทั้งหมดจะปรากฏขึ้นตามลำดับเนื่องจากไม่มีการขนานกัน มีเพียงเธรดเดียวเท่านั้นที่จะเรียกใช้โค้ด Python ในแต่ละครั้ง "ดังนั้นในขณะที่ Python มีเธรดอยู่เธรดเหล่านี้จะมีประสิทธิภาพเท่ากับ coroutines [1]หลามสามารถเข้ารหัส coroutines yieldหลายฟังก์ชั่นผ่านทางเครื่องกำเนิดไฟฟ้ากับ หากใช้อย่างถูกต้องสิ่งนี้เพียงอย่างเดียวสามารถหลีกเลี่ยงการเรียกกลับนรกส่วนใหญ่ที่รู้จักจาก JavaScript ระบบ async / await ล่าสุดจาก Python 3.5 ทำให้สำนวนแบบอะซิงโครนัสสะดวกยิ่งขึ้นใน Python และรวมการวนรอบเหตุการณ์

    [1]: ในทางเทคนิคแล้วข้อ จำกัด เหล่านี้ใช้กับ CPython เท่านั้นการใช้การอ้างอิง Python การใช้งานอื่น ๆ เช่น Jython เสนอเธรดจริงที่สามารถดำเนินการแบบขนาน แต่ต้องผ่านความยาวมากในการใช้พฤติกรรมที่เทียบเท่า เป็นหลัก: ทุกตัวแปรหรือวัตถุสมาชิกเป็นตัวแปรระเหยเพื่อให้การเปลี่ยนแปลงทั้งหมดเป็นอะตอมและเห็นได้ทันทีในกระทู้ทั้งหมด แน่นอนว่าการใช้ตัวแปรระเหยมีราคาแพงกว่าการใช้ตัวแปรปกติ

  • ฉันไม่รู้เกี่ยวกับ Ruby และ PHP มากพอที่จะย่างมันอย่างเหมาะสม

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

สุดท้ายเรามาพูดถึงความแตกต่างระหว่าง coroutines และ thread:

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

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

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

แล้วมีเว็บเป็น ดังกล่าวข้างต้นเว็บเป็นแบบอะซิงโครนัสโดยเนื้อแท้ คำขอเครือข่ายใช้เวลานาน เว็บเซิร์ฟเวอร์หลายแห่งรักษาเธรดพูลที่เต็มไปด้วยเธรดผู้ปฏิบัติงาน อย่างไรก็ตามเวลาส่วนใหญ่ของเธรดเหล่านี้จะไม่ทำงานเนื่องจากกำลังรอทรัพยากรบางส่วนไม่ว่าจะเป็นการรอเหตุการณ์ I / O เมื่อโหลดไฟล์จากดิสก์รอจนกว่าไคลเอ็นต์จะตอบรับส่วนหนึ่งของการตอบสนองหรือรอจนกว่าจะมีฐานข้อมูล แบบสอบถามเสร็จสมบูรณ์ NodeJS ได้แสดงให้เห็นอย่างมหัศจรรย์ว่าการออกแบบเซิร์ฟเวอร์แบบอะซิงโครนัสและเหตุการณ์ที่ตามมานั้นทำงานได้ดีมาก เห็นได้ชัดว่า JavaScript นั้นไกลจากภาษาเดียวที่ใช้สำหรับเว็บแอปพลิเคชันดังนั้นจึงมีแรงจูงใจที่ยิ่งใหญ่สำหรับภาษาอื่น ๆ (สังเกตได้ใน Python และ C #) เพื่อให้การเขียนโปรแกรมเว็บแบบอะซิงโครนัสง่ายขึ้น


ฉันขอแนะนำให้คุณหาแหล่งที่มาของย่อหน้าที่สี่เพื่อหลีกเลี่ยงความเสี่ยงต่อการลอกเลียนแบบมันเกือบจะเหมือนกับแหล่งอื่น ๆ ที่ฉันได้อ่านมา นอกจากนี้ในขณะที่มีคำสั่งที่มีขนาดเล็กเหนือหัวกว่าเธรดประสิทธิภาพของ coroutines จะไม่สามารถทำให้ง่ายขึ้นไปที่ "การเรียกใช้ฟังก์ชันทางอ้อม" ดูรายละเอียดเกี่ยวกับกระตุ้น implementaitons coroutine ที่นี่และที่นี่
WHN

1
@snb เกี่ยวกับการแก้ไขที่คุณแนะนำ: GIL อาจเป็นรายละเอียดการติดตั้ง CPython แต่ปัญหาพื้นฐานคือภาษา Python ไม่มีโมเดลหน่วยความจำที่ชัดเจนซึ่งระบุการกลายพันธุ์แบบขนานของข้อมูล GIL เป็นแฮ็คเพื่อหลีกเลี่ยงปัญหาเหล่านี้ แต่การใช้งานหลามกับความเท่าเทียมที่แท้จริงจะต้องผ่านช่วงที่ดีที่จะให้ความหมายเทียบเท่าเช่นตามที่กล่าวไว้ในหนังสือ Jython โดยทั่วไป: ทุกตัวแปรหรือฟิลด์วัตถุจะต้องเป็นตัวแปรระเหยที่มีราคาแพง
amon

3
@snb เกี่ยวกับการคัดลอกผลงาน: การลอกเลียนผลงานเป็นการนำเสนอแนวคิดที่เป็นเท็จโดยเฉพาะอย่างยิ่งในบริบททางวิชาการ มันเป็นข้อกล่าวหาที่ร้ายแรงแต่ฉันแน่ใจว่าคุณไม่ได้หมายความอย่างนั้น ย่อหน้า“ เธรดเป็นเหมือนกระบวนการ” เพียงเน้นย้ำถึงข้อเท็จจริงที่รู้จักกันดีตามที่สอนในการบรรยายหรือหนังสือเกี่ยวกับระบบปฏิบัติการ เนื่องจากมีเพียงหลายวิธีในการใช้ถ้อยคำให้รัดกุมข้อเท็จจริงเหล่านี้ฉันจึงไม่แปลกใจที่ย่อหน้าที่คุณคุ้นเคย
amon

ผมไม่ได้เปลี่ยนความหมายจะบ่งบอกว่างูหลามได้มีรูปแบบหน่วยความจำ นอกจากนี้การใช้สารระเหยไม่ได้ลดประสิทธิภาพการระเหยเพียงอย่างเดียวนั่นหมายความว่าคอมไพเลอร์ไม่สามารถปรับตัวแปรให้เหมาะสมในวิธีที่มันสามารถสันนิษฐานได้ว่าตัวแปรจะไม่เปลี่ยนแปลงโดยไม่มีการดำเนินการที่ชัดเจนในบริบทปัจจุบัน ในโลก Jython สิ่งนี้อาจมีความสำคัญเนื่องจากกำลังจะใช้การรวบรวม VM JIT แต่ในโลก CPython คุณไม่ต้องกังวลเกี่ยวกับการเพิ่มประสิทธิภาพ JIT ตัวแปรที่ระเหยได้ของคุณจะอยู่ในพื้นที่รันไทม์ของล่ามซึ่งไม่มีการปรับให้เหมาะสม .
WHN

7

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

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

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


4
แต่ coroutines นั้นไม่ได้มีการจัดการระบบปฏิบัติการ ระบบปฏิบัติการไม่ทราบว่า coroutine คืออะไรซึ่งแตกต่างจากเส้นใย C ++
overexchange

ระบบปฏิบัติการจำนวนมากมี coroutines
Jörg W Mittag

coroutines เช่น python และ Javascript ES6 + ไม่ใช่มัลติโพรเซส? ผู้ที่บรรลุภารกิจขนานกันอย่างไร?
WHN

1
@Melael การฟื้นฟู "ล่าสุด" ของ coroutines มาจาก python และ javascript ซึ่งทั้งคู่ไม่สามารถทำคู่ขนานกับ coroutines ได้ตามที่ฉันเข้าใจ นั่นคือการพูดว่าคำตอบนี้ไม่ถูกต้องเนื่องจากงานของนกแก้วไม่ใช่เหตุผลที่ coroutines คือ "back" เลย นอกจากนี้ Luas ก็ไม่ได้มีตัวประมวลผลหลายตัวด้วยใช่ไหม แก้ไข: ฉันเพิ่งรู้ว่าคุณไม่ได้พูดถึงเรื่องความเท่าเทียม แต่ทำไมคุณถึงตอบฉันตั้งแต่แรก? ตอบกลับ dlasalle เนื่องจากเห็นได้ชัดว่าพวกเขาผิดเกี่ยวกับเรื่องนี้
WHN

3
@ ข้อมูลที่ไม่มีพวกเขาไม่สามารถแม้จะมีความจริงที่ว่ามันบอกว่า "ทำงานใน parrallel" ที่ไม่ได้หมายความว่ารหัสใด ๆ ที่ทำงานทางร่างกายในเวลาเดียวกัน GIL จะหยุดการทำงานและ async จะไม่วางไข่แยกกระบวนการที่จำเป็นสำหรับการประมวลผลหลายตัวใน CPython (แยก GIL) Async ทำงานร่วมกับผลตอบแทนในหัวข้อเดียว เมื่อพวกเขาพูดว่า "parralel" พวกเขาจริง ๆ แล้วหมายถึงฟังก์ชั่นหลายฟังก์ชั่นที่ทำงานกับฟังก์ชั่นอื่น ๆ และการดำเนินการฟังก์ชั่นinterleving Python async ไม่สามารถทำงานแบบขนานได้เนื่องจาก impl ตอนนี้ฉันมีสามภาษาที่ไม่ทำ corralines, Lua, Javascript และ Python
WHN

5

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

เธรดเริ่มเข้ามาในภายหลังเนื่องจากในยุค 70 หรือ 80 ระบบปฏิบัติการที่จริงจังทั้งหมดสนับสนุนพวกเขา (และโดย 90s หรือแม้แต่ Windows!) และพวกมันก็กว้างกว่า และใช้งานง่ายกว่า ทันใดนั้นทุกคนคิดว่าหัวข้อเป็นเรื่องใหญ่ต่อไป

ในช่วงปลายยุค 90 รอยแตกก็เริ่มปรากฏขึ้นและในช่วงต้นยุค 2000 มันก็เห็นได้ชัดว่ามีปัญหาร้ายแรงกับกระทู้:

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

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

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

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

5

คำนำ

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

การใช้งานที่ทันสมัย ​​(ทำไมพวกเขาถึงกลับมา)

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

ด้วยการใช้คีย์เวิร์ด Yield เพื่อสร้างเครื่องกำเนิดไฟฟ้า (ซึ่งเป็นส่วนหนึ่งของการประเมินแบบสันหลังยาว) ในภาษาเช่น Python และ C #, coroutines, ในการใช้งานที่ทันสมัยไม่เพียงเป็นไปได้ แต่ยังเป็นไปได้โดยไม่ต้องมีไวยากรณ์พิเศษในภาษา (แม้ว่าหลามในที่สุดก็เพิ่มบิตเพื่อช่วย) ร่วมช่วยเหลือเกี่ยวกับการปฏิบัติ evaulation ขี้เกียจกับความคิดของอนาคต sซึ่งถ้าคุณไม่จำเป็นต้องมีค่าของตัวแปรในช่วงเวลาที่คุณจะสามารถชะลอการซื้อจริงมันจนกว่าคุณจะขอค่าที่ (ช่วยให้คุณสามารถใช้ค่าและขี้เกียจประเมินมันในเวลาที่แตกต่างจากการเริ่มต้น)

นอกเหนือจากการประเมินผลขี้เกียจ แต่โดยเฉพาะอย่างยิ่งใน WebSphere เหล่านี้ขั้นตอนการร่วมช่วยแก้ไขการเรียกกลับนรก Coroutines มีประโยชน์ในการเข้าถึงฐานข้อมูลธุรกรรมออนไลน์ ui ฯลฯ ซึ่งเวลาในการประมวลผลบนเครื่องไคลเอ็นต์จะไม่ส่งผลให้เข้าถึงสิ่งที่คุณต้องการได้เร็วขึ้น Threading สามารถ fullfill สิ่งเดียวกัน แต่ต้องมากขึ้นค่าใช้จ่ายในรูปทรงกลมนี้และในทางตรงกันข้ามกับ coroutines, จริงมีประโยชน์สำหรับงานขนาน

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

ตัวอย่างสมัยใหม่

Coroutines ในภาษาเช่น Javascript, Lua, C # และ Python ล้วนได้รับการนำไปใช้งานโดยแต่ละฟังก์ชั่นที่ให้การควบคุมเธรดหลักไปยังฟังก์ชั่นอื่น ๆ (ไม่เกี่ยวกับการเรียกระบบปฏิบัติการ)

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

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

แก้ไข: c ++ coroutine2 Boost ทำงานในลักษณะเดียวกันและคำอธิบายของพวกเขาควรจะให้ภาพที่ดีขึ้นของสิ่งที่ผมพูดเกี่ยวกับ yeilds, ดูที่นี่ อย่างที่คุณเห็นไม่มี "กรณีพิเศษ" ในการใช้งานสิ่งต่าง ๆ เช่นเส้นใยเพิ่มเป็นข้อยกเว้นกฎและแม้แต่ต้องประสานชัดเจน

EDIT2: เนื่องจากมีคนคิดว่าฉันกำลังพูดถึงระบบตามงาน c # ฉันไม่ได้ ฉันกำลังพูดถึงระบบของ Unityและการติดตั้งใช้งานที่ไร้เดียงสา


@ T.Sar ฉันไม่เคยระบุว่า C # มี coroutines "natural" ใด ๆ ทั้ง C ++ (อาจเปลี่ยน) และไม่ใช้ Python (และยังมีพวกมันอยู่) และทั้งสามมีการใช้งานตามปกติร่วม แต่การใช้งาน C # ทั้งหมดของ coroutines (เช่นเดียวกับในเอกภาพ) จะขึ้นอยู่กับผลผลิตตามที่ฉันอธิบาย นอกจากนี้การใช้งาน "แฮ็ค" ของคุณที่นี่ก็ไม่มีความหมายฉันเดาว่าทุกโปรแกรมเป็นแฮ็คเพราะมันไม่ได้ถูกกำหนดในภาษาเสมอไป ฉันไม่ได้ผสมระบบ C # ตามงาน "กับอะไรฉันไม่ได้พูดถึงมัน
WHN

ฉันขอแนะนำให้ทำให้คำตอบของคุณชัดเจนยิ่งขึ้น C # มีทั้งแนวคิดของการรอคำสั่งและระบบความเท่าเทียมบนพื้นฐานของงาน - การใช้ C # และคำเหล่านั้นในขณะที่ให้ตัวอย่างเกี่ยวกับงูหลามเกี่ยวกับวิธีที่หลามไม่ขนานกันอย่างแท้จริงสามารถทำให้เกิดความสับสนอย่างหนัก และลบประโยคแรกของคุณออกโดยไม่จำเป็นที่จะต้องโจมตีผู้ใช้รายอื่นโดยตรงในคำตอบเช่นนั้น
T. Sar - Reinstate Monica
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.