Asynchronous vs Multithreading - มีความแตกต่างหรือไม่?


134

การโทรแบบอะซิงโครนัสสร้างเธรดใหม่เสมอหรือไม่ อะไรคือความแตกต่างระหว่างทั้งสอง?

การเรียกแบบอะซิงโครนัสสร้างหรือใช้เธรดใหม่เสมอหรือไม่

Wikipedia พูดว่า :

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

ฉันรู้ว่าการโทรแบบ async สามารถทำได้ในเธรดเดียว? เป็นไปได้อย่างไร?



1
JavaScript ไม่มีเธรด แต่มีการเรียกเมธอดแบบอะซิงโครนัส
Ajedi32

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

คำตอบ:


83

คำถามนี้ใกล้จะกว้างเกินไปที่จะตอบ

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

อะซิงโครนัสหมายถึงเธรดการโทรไม่ได้นั่งรอการตอบสนองและกิจกรรมอะซิงโครนัสไม่เกิดขึ้นในเธรดการโทร

ยิ่งไปกว่านั้นคุณจะต้องเจาะจงมากขึ้น


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

6
@ ไมเคิล - คุณช่วยอธิบายได้ไหมว่าการเขียนโปรแกรมแบบอะซิงโครนัสอาจเกิดขึ้นในเธรดเดียวด้วยตัวอย่างได้อย่างไร
Kumar Vaibhav

7
@KumarVaibhav - ตัวอย่างที่พบบ่อยที่สุดคือเมื่อเธรดเดียวทำงานกับรายการจากคิว (เช่นคิวข้อความของ Windows) หากโปรแกรมมีนิสัยในการส่งรายการไปยังคิวของตัวเอง (รูปแบบทั่วไป) บิตของโค้ดที่ส่งรายการจะไม่รอให้การดำเนินการเสร็จสิ้น แต่จะส่งคืนเท่านั้น การดำเนินการจะได้รับการดูแลตามกำหนดโดยลูปหลัก
Michael Kohne

3
อาจมีความแตกต่างระหว่างวิธีการเขียนโค้ดและวิธีดำเนินการ ตัวอย่างเช่นใน C # ฉันสามารถมีเมธอดที่เริ่มงาน async ได้เมธอดของฉันคือ async รับรู้อย่างสมบูรณ์และสามารถทำสิ่งอื่น ๆ ได้โดยไม่ต้องรอให้งานเสร็จสมบูรณ์ อย่างไรก็ตาม CLR ยังสามารถตัดสินใจที่จะอินไลน์งานของฉันและดำเนินการพร้อมกันได้
ไมค์

เธรดใดที่รันงานที่รอคอย เมธอดที่มีเครื่องหมาย a-sync จะถูกดำเนินการพร้อมกันจนกว่าจะถึงคีย์เวิร์ด await ณ จุดนี้เธรดใดที่รันงานที่รอคอยนี้

103

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

Abstractions และ API ระดับสูงที่พบบ่อยจะไม่เปิดเผย API แบบอะซิงโครนัสพื้นฐานที่พร้อมใช้งานจากระบบปฏิบัติการและฮาร์ดแวร์พื้นฐาน ในกรณีเหล่านี้โดยปกติแล้วการสร้างเธรดเพื่อดำเนินการแบบอะซิงโครนัสจะง่ายกว่าแม้ว่าเธรดที่เกิดจะกำลังรอการดำเนินการ I / O ก็ตาม

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


1
อธิบายได้ดีขอบคุณ; แต่ฉันมีคำถามที่นี่ คุณได้กล่าวไว้ว่า "ตัวอย่างเช่นถ้าการดำเนินการ async เป็น I / O CPU ไม่ต้องรอให้ I / O เสร็จสมบูรณ์เพียงแค่ต้องเริ่มการดำเนินการ" คำถามของฉันคือเมื่อโปรแกรมเป็นเธรดเดียวและพูดในโค้ดบรรทัดที่ 3 คุณเรียกการดำเนินการ I / O จากนั้นคุณจะเริ่มการดำเนินการในบรรทัดที่ 3 และดำเนินการบรรทัดที่ 4 ได้อย่างไรโดยไม่ต้องรอให้การดำเนินการ I / O เสร็จสมบูรณ์ เหรอ? สำหรับฉันฉันต้องใส่รหัสในบรรทัดที่ 3 ในเธรดใหม่เพื่อให้บรรทัดที่ 4 ดำเนินการได้โดยไม่ต้องรอให้การดำเนินการ I / O เสร็จสิ้น [มุมมอง Java pgm]
spiderman

1
เหตุผลก็คือแม้ว่า CPU จะไม่ต้องรอ แต่ CPU จะรอให้การดำเนินการ I / O เสร็จสิ้น ... ฉันเชื่อว่าย่อหน้าที่สองของคุณคือคำตอบสำหรับคำถามของฉัน ในกรณีเช่นนี้ฉันต้องสรุปว่าใน Java การเรียกแบบอะซิงโครนัสจำเป็นต้องดำเนินการในเธรดอื่น โปรดแก้ไขฉันหากฉันผิดหรือแจ้งให้เราทราบหากฉันต้องโพสต์ SO qn ใหม่
spiderman

@spiderman บางภาษาเช่น Node.js มีรูปแบบการเขียนโปรแกรมแบบ async ภาษาและรันไทม์จัดเตรียมบิวด์อินที่อนุญาตให้เรียกใช้บรรทัด 4 ในเธรดเดียวกันก่อนที่การดำเนินการ IO จะเสร็จสิ้น สิ่งนี้ทำได้โดยบรรทัดที่ 3 ให้การเรียกกลับที่รันไทม์จะเรียกใช้เมื่อ IO เสร็จสิ้น
jrahhali

@spiderman บางที ... ฟังก์ชั่น Async ของระบบปฏิบัติการจะส่งคืนเท็จหรือบางอย่างโดยตรง
Byeongin Yoon

18

ไม่การโทรแบบอะซิงโครนัสไม่เกี่ยวข้องกับเธรดเสมอไป

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


12

JavaScript เป็นเธรดเดียวและแบบอะซิงโครนัส ตัวอย่างเช่นเมื่อคุณใช้ XmlHttpRequest คุณให้ฟังก์ชันเรียกกลับที่จะดำเนินการแบบอะซิงโครนัสเมื่อการตอบกลับส่งกลับ

จอห์นเรซิกมีคำอธิบายที่ดีของปัญหาที่เกี่ยวข้องกับวิธีการจับเวลาทำงานใน JavaScript


12

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


ฉันจะไม่เห็นด้วยเล็กน้อย ฉันเขียนเซิร์ฟเวอร์ HTTP เธรดเดียวที่จัดการคำขอพร้อมกันหลายรายการโดยใช้ async IO เสร็จสิ้น Async ไม่ต้องการให้สิ่งต่างๆเกิดขึ้นในหลายเส้นทางของการดำเนินการ แต่หมายความว่าสตรีมการประมวลผลหลายรายการสามารถทับซ้อนกันได้ อีกวิธีหนึ่งในการตรวจสอบก็คือบน OS เธรดเดียวฉันสามารถมี 2 กระบวนการที่ทำงาน "พร้อมกัน" ได้ จากมุมมองของแต่ละกระบวนการพวกเขากำลังทำงานพร้อมกัน อย่างไรก็ตามจากมุมมองของระบบปฏิบัติการมันทำงานแบบ async
Mike

11

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


@dmckee - เป็นที่น่าสนใจว่าระบบต่างๆมีวิวัฒนาการอย่างไรในลักษณะที่คล้ายคลึงกัน
OtávioDécio

8

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

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

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


7

บางระบบอนุญาตให้คุณใช้ประโยชน์จากการทำงานพร้อมกันในเคอร์เนลสำหรับสิ่งอำนวยความสะดวกบางอย่างโดยใช้การเรียกกลับ สำหรับอินสแตนซ์ที่ค่อนข้างคลุมเครือจะมีการใช้การเรียกกลับ IO แบบอะซิงโครนัสเพื่อใช้งานเซิร์ฟเวอร์อินเทอร์เน็ตที่ไม่ปิดกั้นย้อนกลับไปในช่วงวันทำงานมัลติทาสก์ที่ไม่มีการป้องกันล่วงหน้าของ Mac System 6-8

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


5

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

มีตัวอย่างของโปรแกรมแบบอะซิงโครนัสเธรดเดียว สิ่งที่ต้องการ:

...do something
...send some async request
while (not done)
    ...do something else
    ...do async check for results

2

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

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


นี่เป็นความจริงในบางระบบ แต่ไม่ใช่ทั้งหมด Unix ไม่ต้องการให้คุณวางไข่หรือใช้เธรดอื่นเว้นแต่คุณจะเรียกเคอร์เนลเธรดอื่นซึ่งฉันคิดว่าเป็นวิธีหนึ่งในการดู
Craig S

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