JavaScript รับประกันว่าจะเป็นแบบเธรดเดียวหรือไม่


610

JavaScript เป็นที่รู้จักกันว่าเป็นเธรดเดี่ยวในการใช้งานเบราว์เซอร์สมัยใหม่ทั้งหมด แต่มีการระบุไว้ในมาตรฐานใด ๆ หรือเป็นเพียงประเพณี? ปลอดภัยไหมที่จะถือว่า JavaScript เป็นเธรดเดียว?


25
ในบริบทของเบราว์เซอร์อาจ แต่บางโปรแกรมอนุญาตให้คุณปฏิบัติต่อ JS ในระดับสูงสุดและให้การเชื่อมสำหรับ C ++ libs อื่น ๆ ตัวอย่างเช่น flusspferd (การเชื่อมโยง C ++ สำหรับ JS - AWESOME BTW) กำลังทำบางสิ่งด้วย JS แบบมัลติเธรด มันขึ้นอยู่กับบริบท
NG

11
นี่คือต้องอ่าน: developer.mozilla.org/en/docs/Web/JavaScript/EventLoop
RickyA

คำตอบ:


583

นั่นเป็นคำถามที่ดี ฉันชอบที่จะพูดว่า“ ใช่” ฉันทำไม่ได้

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

(*: เพิกเฉยต่อคำถามว่าเบราว์เซอร์ใช้งานเอ็นจิน JS ของตนโดยใช้หนึ่ง OS-thread หรือไม่หรือ WebWorkers มีการ จำกัด เธรดการดำเนินการที่ จำกัด อื่น ๆ )

อย่างไรก็ตามในความเป็นจริงมันไม่เป็นความจริงในทางที่น่ารังเกียจ

กรณีที่พบบ่อยที่สุดคือเหตุการณ์ทันที เบราว์เซอร์จะเริ่มต้นสิ่งเหล่านี้ทันทีเมื่อโค้ดของคุณทำสิ่งที่ทำให้เกิด:

var l= document.getElementById('log');
var i= document.getElementById('inp');
i.onblur= function() {
    l.value+= 'blur\n';
};
setTimeout(function() {
    l.value+= 'log in\n';
    l.focus();
    l.value+= 'log out\n';
}, 100);
i.focus();
<textarea id="log" rows="20" cols="40"></textarea>
<input id="inp">

ให้ผลลัพธ์log in, blur, log outกับทุกคนยกเว้น IE เหตุการณ์เหล่านี้ไม่เพียงเกิดขึ้นเพราะคุณโทรติดต่อfocus()โดยตรงเหตุการณ์เหล่านี้อาจเกิดขึ้นเพราะคุณโทรalert()หรือเปิดหน้าต่างป๊อปอัปหรือสิ่งอื่นใดที่ขยับโฟกัส

นอกจากนี้ยังสามารถส่งผลให้เกิดเหตุการณ์อื่น ๆ ตัวอย่างเช่นเพิ่มi.onchangeผู้ฟังและพิมพ์บางสิ่งบางอย่างในอินพุตก่อนที่การfocus()โทรจะแยกออกจากกันและลำดับของการบันทึกคือlog in, change, blur, log outยกเว้นใน Opera ที่เป็นlog in, blur, log out, changeและ IE อยู่ที่log in, change, log out, blurใด

ในทำนองเดียวกันการเรียกclick()องค์ประกอบที่ให้มันเรียกonclickตัวจัดการทันทีในเบราว์เซอร์ทั้งหมด (อย่างน้อยก็สอดคล้องกัน!)

(ฉันใช้on...คุณสมบัติตัวจัดการเหตุการณ์โดยตรงที่นี่ แต่สิ่งเดียวกันเกิดขึ้นกับaddEventListenerและattachEvent)

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

var l= document.getElementById('log');
document.getElementById('act').onclick= function() {
    l.value+= 'alert in\n';
    alert('alert!');
    l.value+= 'alert out\n';
};
window.onresize= function() {
    l.value+= 'resize\n';
};
<textarea id="log" rows="20" cols="40"></textarea>
<button id="act">alert</button>

กดalertและคุณจะได้รับกล่องโต้ตอบเป็นกิริยาช่วย ไม่มีสคริปต์ทำงานอีกต่อไปจนกว่าคุณจะยกเลิกบทสนทนานั้นใช่ไหม Nope ปรับขนาดหน้าต่างหลักและคุณจะได้รับalert in, resize, alert outใน textarea

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

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

สถานที่ที่สามารถสร้างเหตุการณ์ที่คุณสามารถสร้างได้ในขณะที่สคริปต์ยังคงอยู่ในเธรด:

  • เมื่อป๊อปอัปกิริยา ( alert, confirm, prompt) จะเปิดในเบราว์เซอร์ทั้งหมด แต่โอเปร่า;

  • ระหว่างshowModalDialogเบราว์เซอร์ที่รองรับ

  • กล่องโต้ตอบ“ สคริปต์ในหน้านี้อาจไม่ว่าง ... ” แม้ว่าคุณจะเลือกที่จะให้สคริปต์ทำงานต่อไปได้อนุญาตให้เหตุการณ์เช่นปรับขนาดและเบลอไล่และจัดการแม้ในขณะที่สคริปต์อยู่ตรงกลาง ไม่ว่างในวงยกเว้นใน Opera

  • เมื่อสักครู่ที่ผ่านมาสำหรับฉันใน IE ด้วยปลั๊กอิน Sun Java การเรียกใช้วิธีการใด ๆ บนแอปเพล็ตอาจทำให้เหตุการณ์เริ่มทำงานและสคริปต์จะถูกป้อนอีกครั้ง นี่เป็นข้อผิดพลาดตามกำหนดเวลาเสมอและเป็นไปได้ที่ Sun จะแก้ไขมันตั้งแต่ (ฉันหวังอย่างนั้น)

  • อาจจะมากกว่า ไม่นานมานี้ที่ฉันทำการทดสอบและเบราว์เซอร์มีความซับซ้อนเพิ่มขึ้น

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

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


14
@JP: โดยส่วนตัวแล้วฉันไม่ต้องการที่จะรู้ทันทีเพราะมันหมายความว่าฉันต้องระวังว่ารหัสของฉันเป็นผู้เข้าใหม่อีกครั้งการเรียกรหัสเบลอของฉันจะไม่ส่งผลกระทบต่อสถานะที่รหัสภายนอกบางส่วนอาศัยอยู่ มีหลายกรณีเกินไปที่การเบลอภาพเป็นผลข้างเคียงที่ไม่คาดคิดที่จะต้องจับภาพทุกภาพ และน่าเสียดายแม้ว่าคุณจะต้องการมันก็ไม่น่าเชื่อถือ! IE เริ่มทำงานblur หลังจากรหัสของคุณคืนการควบคุมไปยังเบราว์เซอร์
bobince

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

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

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

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

115

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

เพิ่มไปที่ข้อเท็จจริงที่ว่าHTML5 ระบุ Web Workers (API มาตรฐานที่ชัดเจนสำหรับโค้ดจาวาสคริปต์แบบมัลติเธรด) ที่แนะนำมัลติเธรดลงใน Javascript พื้นฐานจะไม่มีประโยชน์ส่วนใหญ่

( หมายเหตุถึงผู้แสดงความคิดเห็นอื่น ๆ :ถึงแม้ว่าsetTimeout/setIntervalเหตุการณ์ HTTP onload ขอ (XHR) และกิจกรรม UI (คลิก, โฟกัส, ฯลฯ ) ให้การแสดงผลที่หยาบคายของมัลติเธรด - พวกเขายังคงดำเนินการทั้งหมดในไทม์ไลน์เดียว - หนึ่งที่ เวลา - ดังนั้นแม้ว่าเราจะไม่ทราบคำสั่งดำเนินการของพวกเขาล่วงหน้าไม่จำเป็นต้องกังวลเกี่ยวกับสภาพภายนอกที่เปลี่ยนแปลงในระหว่างการดำเนินการของตัวจัดการเหตุการณ์ฟังก์ชั่นที่กำหนดเวลาหรือโทรกลับ XHR)


21
ฉันเห็นด้วย. หากการเพิ่มหลายเธรดถูกเพิ่มลงใน Javascript ในเบราว์เซอร์ก็จะผ่าน API ที่ชัดเจน (เช่น Web Workers) เช่นเดียวกับภาษาที่จำเป็นทั้งหมด นั่นเป็นวิธีเดียวที่สมเหตุสมผล
Dean Harding

1
โปรดทราบว่ามีเพียงหนึ่งเดียว เธรด JS หลัก แต่บางสิ่งรันในเบราว์เซอร์แบบขนาน มันไม่ใช่แค่ความประทับใจในมัลติเธรด คำขอมีการทำงานแบบขนานจริง ๆ listeners ที่คุณกำหนดใน JS รันแบบหนึ่งต่อหนึ่ง แต่คำร้องขอขนานกันอย่างแท้จริง
Nux

16

ใช่แม้ว่าคุณยังสามารถประสบปัญหาของการเขียนโปรแกรมพร้อมกัน (ส่วนใหญ่เป็นเงื่อนไขการแข่งขัน) เมื่อใช้ API แบบอะซิงโครนัสใด ๆ เช่น setInterval และการเรียกกลับ xmlhttp


10

ใช่แม้ว่า Internet Explorer 9 จะรวบรวม Javascript ของคุณในเธรดแยกต่างหากเพื่อเตรียมการดำเนินการกับเธรดหลัก สิ่งนี้ไม่ได้เปลี่ยนแปลงอะไรสำหรับคุณในฐานะโปรแกรมเมอร์


8

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

ฉันคิดว่ากระบวนทัศน์ที่ไม่มีการบล็อกเธรดเดี่ยวมาจากความต้องการใช้งานจาวาสคริปต์ในเบราว์เซอร์ที่ UI ไม่ควรบล็อก

Nodejsได้ปฏิบัติตามแนวทางของเบราว์เซอร์แล้ว

แรดเครื่องยนต์ แต่สนับสนุนการทำงาน js รหัสในหัวข้อที่แตกต่างกัน การประหารชีวิตไม่สามารถแบ่งปันบริบท แต่พวกเขาสามารถแบ่งปันขอบเขต สำหรับกรณีเฉพาะนี้เอกสารระบุสถานะ:

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

จากการอ่านเอกสารของแรดฉันสรุปได้ว่าบางคนสามารถเขียน API ของ javascript ที่วางไข่เธรด javascript ใหม่ แต่ api นั้นเป็นแรดเฉพาะ (เช่นโหนดสามารถวางไข่กระบวนการใหม่)

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

การสร้างเบราว์เซอร์และโหนดให้เป็นแบบที่ฉันเห็นคือ:

    1. คือทุก jsรหัสดำเนินการในหัวข้อเดียว ? : ใช่
    1. รหัสjsสามารถเป็นสาเหตุให้เธรดอื่นรันได้หรือไม่? : ใช่
    1. Can หัวข้อเหล่านี้บริบทการดำเนินการกลายพันธุ์ js : เลขที่แต่พวกเขาสามารถ (โดยตรง / อ้อม ()?) ผนวกกับคิวงานจากการที่ ผู้ฟังสามารถกลายพันธุ์บริบทการดำเนินการ แต่อย่าหลงกลผู้ฟังต่างวิ่งไปตามเธรดหลักอีกครั้ง

ดังนั้นในกรณีของเบราว์เซอร์และ nodejs (และอาจจะมากของเครื่องมืออื่น ๆ ) จาวาสคริปต์ไม่ได้ multithreaded แต่เครื่องยนต์ตัวเองเป็น


อัพเดทเกี่ยวกับเว็บเวิร์ค:

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

อย่างไรก็ตาม: ผู้ทำงานกับเว็บจะไม่แก้ปัญหาของเธรดดั้งเดิมที่สามารถแบ่งปันบริบทการดำเนินการได้ กฎที่ 2 และ 3 ข้างต้นยังคงมีผลอยู่แต่คราวนี้โค้ดเธรดถูกสร้างโดยผู้ใช้ (ผู้เขียนโค้ด js) ในจาวาสคริปต์

สิ่งเดียวที่ต้องพิจารณาคือจำนวนเธรดที่สร้างใหม่จากมุมมองประสิทธิภาพ (และไม่ใช่การทำงานพร้อมกัน ) ดูด้านล่าง:

เกี่ยวกับความปลอดภัยของด้าย :

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

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


PS

นอกจากทฤษฎีแล้วให้เตรียมพร้อมเกี่ยวกับมุมและข้อผิดพลาดที่อธิบายไว้ในคำตอบที่ยอมรับได้เสมอ


7

JavaScript / ECMAScript ถูกออกแบบมาให้ใช้งานได้จริงภายในสภาพแวดล้อมโฮสต์ นั่นคือ JavaScript ไม่ได้ทำอะไรเลยเว้นแต่ว่าสภาพแวดล้อมของโฮสต์ตัดสินใจที่จะแยกวิเคราะห์และดำเนินการสคริปต์ที่กำหนดและให้วัตถุสภาพแวดล้อมที่ให้ JavaScript มีประโยชน์จริง ๆ (เช่น DOM ในเบราว์เซอร์)

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


7

ที่จริงแล้วหน้าต่างหลักสามารถสื่อสารกับหน้าต่างลูกหรือพี่น้องหรือเฟรมที่มีเธรดการดำเนินการของตัวเองทำงาน


6

@ Bobince ได้ให้คำตอบที่ทึบแสงจริงๆ

Riffing จากคำตอบของMárÖrlygsson, Javascript นั้นเป็นแบบเธรดเดียวเสมอเนื่องจากข้อเท็จจริงง่าย ๆ นี้: ทุกอย่างใน Javascript นั้นถูกเรียกใช้งานตามไทม์ไลน์เดียว

นั่นคือคำจำกัดความที่เข้มงวดของภาษาการเขียนโปรแกรมแบบเธรดเดียว


4

เลขที่

ฉันจะต่อต้านฝูงชนที่นี่ แต่ทนกับฉัน สคริปต์ JS เดียวมีวัตถุประสงค์เพื่อให้มีเธรดเดี่ยวที่มีประสิทธิภาพแต่นี่ไม่ได้หมายความว่าสคริปต์นั้นไม่สามารถตีความได้แตกต่างกัน

สมมติว่าคุณมีรหัสต่อไปนี้ ...

var list = [];
for (var i = 0; i < 10000; i++) {
  list[i] = i * i;
}

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

หัวข้อแรก

for (var i = 0; i < 5000; i++) {
  list[i] = i * i;
}

กระทู้ที่สอง

for (var i = 5000; i < 10000; i++) {
  list[i] = i * i;
}

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

ในขณะที่ฉันไม่ทราบว่า VM ตรวจจับโค้ดแบบขนานได้เช่นนี้ดูเหมือนว่าอาจมีอยู่ในอนาคตสำหรับ JIT VM เนื่องจากอาจให้ความเร็วที่มากกว่าในบางสถานการณ์

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

// like "use strict" this enables certain features on compatible VMs.
"use parallel";

var list = [];

// This string, which has no effect on incompatible VMs, enables threading on
// this loop.
"parallel for";
for (var i = 0; i < 10000; i++) {
  list[i] = i * i;
}

เนื่องจาก Web Workers กำลังมาถึง Javascript มันไม่น่าเป็นไปได้ที่ระบบ uglier นี้จะมีอยู่ แต่ฉันคิดว่ามันปลอดภัยที่จะพูดว่า Javascript นั้นเป็นเธรดเดี่ยวตามประเพณี


2
คำจำกัดความภาษาส่วนใหญ่ได้รับการออกแบบให้มีเธรดเดียวอย่างมีประสิทธิภาพแม้ว่าและระบุว่าอนุญาตให้ใช้มัลติเธรดได้ตราบใดที่เอฟเฟกต์เหมือนกัน (เช่น UML)
jevon

1
ฉันได้เห็นด้วยกับคำตอบเพียงเพราะปัจจุบัน ECMAScript ทำให้ไม่มีบทบัญญัติ (แม้ว่าเนื้อหาที่ผมคิดว่าเดียวกันสามารถกล่าวว่าสำหรับ C) สำหรับพร้อมกันECMAScript บริบทการดำเนินการ จากนั้นเหมือนคำตอบนี้ผมขอยืนยันว่าการดำเนินการใด ๆ ที่จะมีหัวข้อพร้อมกันความสามารถในการแก้ไขรัฐร่วมกันเป็น ECMAScript ขยาย
2864740

3

Chrome เป็นมัลติโปรเซสเซอร์และฉันคิดว่าทุกกระบวนการเกี่ยวข้องกับรหัส Javascript ของตัวเอง แต่เท่าที่โค้ดนั้นรู้ก็คือ

ไม่มีการสนับสนุนใด ๆ ใน Javascript สำหรับมัลติเธรดอย่างน้อยไม่ชัดเจนดังนั้นจึงไม่ได้สร้างความแตกต่าง


2

ฉันได้ลองตัวอย่าง @ Bobince ด้วยการแก้ไขเล็กน้อย:

<html>
<head>
    <title>Test</title>
</head>
<body>
    <textarea id="log" rows="20" cols="40"></textarea>
    <br />
    <button id="act">Run</button>
    <script type="text/javascript">
        let l= document.getElementById('log');
        let b = document.getElementById('act');
        let s = 0;

        b.addEventListener('click', function() {
            l.value += 'click begin\n';

            s = 10;
            let s2 = s;

            alert('alert!');

            s = s + s2;

            l.value += 'click end\n';
            l.value += `result = ${s}, should be ${s2 + s2}\n`;
            l.value += '----------\n';
        });

        window.addEventListener('resize', function() {
            if (s === 10) {
                s = 5;
            }

            l.value+= 'resize\n';
        });
    </script>
</body>
</html>

ดังนั้นเมื่อคุณกดเรียกใช้ปิดป๊อปอัปการแจ้งเตือนและทำ "เธรดเดียว" คุณควรเห็นบางสิ่งเช่นนี้:

click begin
click end
result = 20, should be 20

แต่ถ้าคุณพยายามเรียกใช้งานใน Opera หรือ Firefox บน Windows และย่อ / ขยายหน้าต่างด้วยป๊อปอัพแจ้งเตือนบนหน้าจอก็จะมีดังนี้:

click begin
resize
click end
result = 15, should be 20

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


-4

พยายามซ้อนฟังก์ชั่น setTimeout สองตัวในฟังก์ชันซึ่งจะทำงานแบบมัลติเธรด (เช่นตัวจับเวลาภายนอกจะไม่รอให้ตัวประมวลผลภายในเสร็จสิ้นก่อนที่จะเรียกใช้ฟังก์ชัน)


5
chrome ทำสิ่งนี้อย่างถูกวิธี dunno โดยที่ @James เห็นว่ามันเป็นแบบมัลติเธรด ... : setTimeout(function(){setTimeout(function(){console.log('i herd you liek async')}, 0); alert('yo dawg!')}, 0)(สำหรับการบันทึก yo dawg ควรจะมาก่อนเสมอจากนั้นคอนโซลเอาท์พุทจะบันทึก)
Tor Valamo
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.