Tại sao JavaScript không hỗ trợ đa luồng?


269

Đây có phải là một quyết định thiết kế có chủ ý hay là một vấn đề với các trình duyệt hiện tại của chúng tôi sẽ được khắc phục trong các phiên bản sắp tới?


3
Xem thêm câu trả lời cho câu hỏi JavaScript và Chủ đề để biết thông tin về chủ đề nhân viên / công nhân web.
Sam Hasler

115
Xin chào, đồng nghiệp Googler. Bạn có thể nhận thấy rằng mọi thứ ở đây dường như khá cũ (lưu ý câu hỏi này đã được hỏi hơn 5 năm trước.) Kể từ khi được hỏi, các trình duyệt web đã đạt được một số khả năng, theo như tôi có thể nói, là nhiều hoặc ít đa luồng. Hãy xem Công nhân web: msdn.microsoft.com/en-us/hh549259.aspx
ArtOfWarfare

2
Multithread.js kết thúc các Công nhân web và cho phép đa luồng dễ dàng trong JS. Hoạt động trên tất cả các trình duyệt mới, bao gồm cả iOS Safari. :)
kwh

1
Bản sao có thể có của JavaScript và Chủ đề
Matt

Câu trả lời:


194

JavaScript không hỗ trợ đa luồng vì trình thông dịch JavaScript trong trình duyệt là một luồng đơn (AFAIK). Ngay cả Google Chrome cũng sẽ không để JavaScript của một trang web chạy đồng thời vì điều này sẽ gây ra sự cố đồng thời lớn trong các trang web hiện tại. Tất cả Chrome thực hiện là tách nhiều thành phần (các tab, trình cắm, v.v.) khác nhau thành các quy trình riêng biệt, nhưng tôi không thể tưởng tượng một trang duy nhất có nhiều hơn một luồng JavaScript.

Tuy nhiên, bạn có thể sử dụng, như đã được đề xuất, setTimeoutđể cho phép một số loại lập kế hoạch và đồng thời giả mạo. Điều này khiến trình duyệt lấy lại quyền kiểm soát luồng kết xuất và bắt đầu mã JavaScript được cung cấp setTimeoutsau số mili giây đã cho. Điều này rất hữu ích nếu bạn muốn cho phép chế độ xem (những gì bạn thấy) làm mới trong khi thực hiện các thao tác trên nó. Chỉ cần lặp qua các tọa độ ví dụ và cập nhật một phần tử tương ứng sẽ cho phép bạn thấy các vị trí bắt đầu và kết thúc, và không có gì ở giữa.

Chúng tôi sử dụng một thư viện trừu tượng trong JavaScript cho phép chúng tôi tạo các quy trình và luồng được quản lý bởi cùng một trình thông dịch JavaScript. Điều này cho phép chúng tôi chạy các hành động theo cách sau:

  • Quy trình A, Chủ đề 1
  • Quy trình A, Chủ đề 2
  • Quy trình B, Chủ đề 1
  • Quy trình A, Chủ đề 3
  • Quy trình A, Chủ đề 4
  • Quy trình B, Chủ đề 2
  • Tạm dừng quá trình A
  • Quy trình B, Chủ đề 3
  • Quy trình B, Chủ đề 4
  • Quy trình B, Chủ đề 5
  • Bắt đầu quá trình A
  • Quy trình A, Chủ đề 5

Điều này cho phép một số hình thức lập lịch và thực hiện song song, bắt đầu và dừng các luồng, vân vân, nhưng nó sẽ không phải là đa luồng thực sự. Tôi không nghĩ nó sẽ được thực hiện bằng chính ngôn ngữ này, vì đa luồng thực sự chỉ hữu ích nếu trình duyệt có thể chạy một trang đa luồng (hoặc thậm chí nhiều hơn một lõi) và những khó khăn còn lớn hơn hơn các khả năng bổ sung.

Để biết tương lai của JavaScript, hãy xem điều này: https://developer.mozilla.org/presentations/xtech2006/javascript/


73
Tôi nghĩ không bao giờ thực hiện là tầm nhìn quá hẹp. Tôi đảm bảo các ứng dụng web cuối cùng sẽ có thể thực sự đa luồng (nó chỉ hợp lý, khi các ứng dụng web trở nên chiếm ưu thế hơn và phần cứng trở nên song song hơn), và như tôi thấy, vì JavaScript là ngôn ngữ thực tế của phát triển web, nó cuối cùng sẽ phải hỗ trợ đa luồng hoặc được thay thế bằng một cái gì đó.
devios1

6
Không bao giờ có thể là một chút của một tuyên bố quá táo bạo :) nhưng tôi vẫn nghĩ rằng những lợi thế của javascript đa luồng thực sự là không khả thi trong tương lai gần;)
Kamiel Wanrooij

5
Mặc dù tôi sẽ lập luận rằng các nhân viên web đồng thời thông qua một mô hình quy trình hơn là một mô hình luồng. Nhân viên web sử dụng chuyển tin nhắn làm phương tiện liên lạc, đây là một giải pháp tinh tế cho các vấn đề tương tranh 'thông thường' trong các ứng dụng đa luồng. Tôi không chắc liệu chúng có thực sự hoạt động trên cùng một đối tượng như trang chính không. Họ không thể truy cập DOM theo như tôi biết. Hầu hết trong số này là ngữ nghĩa mặc dù, nhân viên web có vẻ hứa hẹn cho tất cả ý định và mục đích.
Kamiel Wanrooij

khó khăn có cách lớn hơn khả năng bổ sung Tôi không chắc bạn có nghĩ đến tất cả các khả năng bổ sung không. Tôi đặc biệt nghĩ về các trường hợp webgl được sử dụng như trong các trò chơi hoặc trực quan hóa đồ họa. Ví dụ, hãy xem xét phiên bản 3D mới của Google Maps. Ở các thành phố có nhiều mô hình 3D, PC của tôi cần ~ 2 phút để tải mọi thứ khi nhiều ngôi nhà phải được kết xuất. Ở một số góc độ nhất định, cả card đồ họa và mạng của tôi đều không hoạt động. Nhưng 1 trong 8 bộ xử lý là 100%. Đa luồng cũng là một mối quan tâm lớn về mặt khung hình / giây vì ví dụ này cho thấy: youtube.com/watch?v=sJ2p982cZFc
Scindix

25

JavaScript đa luồng (với một số hạn chế) có ở đây. Google đã triển khai các công nhân cho Gears và các công nhân đang được đưa vào HTML5. Hầu hết các trình duyệt đã thêm hỗ trợ cho tính năng này.

An toàn luồng dữ liệu được đảm bảo vì tất cả dữ liệu được truyền đến / từ công nhân được tuần tự hóa / sao chép.

Để biết thêm thông tin, đọc:

http://www.whatwg.org/specs/web-workers/c Hiện-work /

http://ejohn.org/blog/web-workers/


8
Nhưng nó không phải là cách tiếp cận đa quy trình hơn là đa luồng? Chủ đề được biết là làm việc trong một đống.
thịt bò

1
@beefeather, đó là sự thật. Đó là một cách tiếp cận quá trình.
Neil

23

Theo truyền thống, JS được dành cho các đoạn mã ngắn, chạy nhanh. Nếu bạn có những tính toán lớn đang diễn ra, bạn đã thực hiện nó trên một máy chủ - ý tưởng về một ứng dụng JS + HTML chạy trong trình duyệt của bạn trong thời gian dài làm những việc không tầm thường là vô lý.

Tất nhiên, bây giờ chúng tôi có điều đó. Tuy nhiên, sẽ cần một chút để các trình duyệt bắt kịp - hầu hết chúng được thiết kế xung quanh một mô hình đơn luồng và việc thay đổi điều đó không dễ dàng. Google Gears xử lý rất nhiều vấn đề tiềm ẩn bằng cách yêu cầu thực thi nền được cách ly - không thay đổi DOM (vì điều đó không an toàn cho luồng), không truy cập các đối tượng được tạo bởi luồng chính (ditto). Mặc dù hạn chế, đây có thể sẽ là thiết kế thiết thực nhất cho tương lai gần, bởi vì nó đơn giản hóa thiết kế của trình duyệt và vì nó giảm rủi ro liên quan đến việc cho phép các lập trình viên JS thiếu kinh nghiệm làm rối tung các luồng ...

@marcio :

Tại sao đó là một lý do để không triển khai đa luồng trong Javascript? Các lập trình viên có thể làm bất cứ điều gì họ muốn với các công cụ họ có.

Vì vậy, sau đó, đừng cung cấp cho họ các công cụ dễ sử dụng đến mức mọi trang web khác tôi mở đều bị sập trình duyệt của tôi. Việc triển khai ngây thơ này sẽ đưa bạn vào thẳng lãnh thổ khiến MS rất đau đầu trong quá trình phát triển IE7: các tác giả bổ trợ đã chơi nhanh và lỏng lẻo với mô hình luồng, dẫn đến các lỗi ẩn rõ ràng khi vòng đời đối tượng thay đổi trên luồng chính . XẤU. Nếu bạn đang viết các tiện ích ActiveX đa luồng cho IE, tôi đoán nó đi kèm với lãnh thổ; không có nghĩa là nó cần phải đi xa hơn thế.


6
"nó làm giảm rủi ro liên quan> trong việc cho phép các lập trình viên JS thiếu kinh nghiệm> loay hoay với các luồng" Tại sao đó là lý do không thực hiện đa luồng trong Javascript? Các lập trình viên có thể làm bất cứ điều gì họ muốn với các công cụ họ có. Nếu nó tốt hay xấu, đó là vấn đề của họ. Với mô hình quy trình Google Chrome, nó thậm chí không thể ảnh hưởng đến các ứng dụng khác. :)
Marcio Aguiar

3
@ Shog9 - "Chúng ta đừng cung cấp cho [lập trình viên] các công cụ dễ sử dụng sai đến mức mọi trang web khác tôi mở đều bị sập trình duyệt của tôi." - Gì? Theo cùng một logic đó, không có ngôn ngữ nào nên có đa luồng, bởi vì nếu họ đề nghị rằng mọi chương trình khác mà bạn đã thử mở sẽ bị sập. Ngoại trừ nó không hoạt động theo cách đó. Luồng tồn tại trong hầu hết các ngôn ngữ và hầu hết các lập trình viên mới làm quen không chạm vào nó, và hầu hết những ngôn ngữ không đưa nó vào sản xuất và những ứng dụng không bao giờ trở nên phổ biến hoặc được sử dụng rộng rãi.
ArtOfWarfare

11

Tôi không biết lý do căn bản cho quyết định này, nhưng tôi biết rằng bạn có thể mô phỏng một số lợi ích của lập trình đa luồng bằng cách sử dụng setTimeout. Bạn có thể ảo tưởng về nhiều quá trình thực hiện cùng một lúc, mặc dù trong thực tế, mọi thứ xảy ra trong một luồng.

Chỉ cần có chức năng của bạn làm một chút công việc, và sau đó gọi một cái gì đó như:

setTimeout(function () {
    ... do the rest of the work...
}, 0);

Và bất kỳ điều gì khác cần làm (như cập nhật giao diện người dùng, hình ảnh hoạt hình, v.v.) sẽ xảy ra khi họ có cơ hội.


Hầu hết các trường hợp tôi muốn sử dụng loopbên trong setTimeoutnhưng dường như không hoạt động. Bạn đã làm bất cứ điều gì như vậy hoặc bạn có một hack? một ví dụ sẽ là mảng 1000 phần tử, tôi dự kiến ​​sẽ sử dụng hai cho các vòng lặp bên trong hai setTimeoutlệnh gọi sao cho các vòng lặp đầu tiên và phần tử in 0..499, các vòng lặp thứ hai xuyên qua và phần tử in 500..999.
benjaminz

Thông thường kỹ thuật là để lưu trạng thái và tiếp tục. Ví dụ: giả sử bạn muốn in 0 đến 1000, bạn có thể in 0 đến 499 và sau đó thực hiện thủ thuật setTimeout với đối số 500. Mã bên trong sẽ biết lấy đối số (500) và bắt đầu vòng lặp từ đó.
Mắt

8

Ý bạn là tại sao ngôn ngữ không hỗ trợ đa luồng hay tại sao các công cụ JavaScript trong trình duyệt không hỗ trợ đa luồng?

Câu trả lời cho câu hỏi đầu tiên là JavaScript trong trình duyệt có nghĩa là được chạy trong hộp cát và theo cách độc lập với máy / HĐH, để thêm hỗ trợ đa luồng sẽ làm phức tạp ngôn ngữ và gắn ngôn ngữ quá chặt chẽ với HĐH.


6

Node.js 10.5+ hỗ trợ các luồng công nhân làm tính năng thử nghiệm (bạn có thể sử dụng nó với cờ --experimental-worker được bật): https://nodejs.org/api/worker_threads.html

Vì vậy, quy tắc là:

  • nếu bạn cần thực hiện các thao tác ràng buộc I / O , thì hãy sử dụng cơ chế bên trong (còn gọi là gọi lại / lời hứa / async-await)
  • nếu bạn cần làm ops CPU bị ràng buộc , sau đó sử dụng các luồng worker.

Chủ đề công nhân được dự định là chủ đề sống lâu, có nghĩa là bạn sinh ra một chủ đề nền và sau đó bạn giao tiếp với nó thông qua tin nhắn đi qua.

Mặt khác, nếu bạn cần thực thi tải CPU nặng với chức năng ẩn danh, thì bạn có thể truy cập https://github.com/wilk/microjob , một thư viện nhỏ được xây dựng xung quanh các luồng công nhân.


4

Như matt b đã nói, câu hỏi không rõ ràng lắm. Giả sử rằng bạn đang hỏi về hỗ trợ đa luồng trong ngôn ngữ: bởi vì hiện tại không cần thiết cho 99.999% ứng dụng đang chạy trong trình duyệt. Nếu bạn thực sự cần nó, có cách giải quyết (như sử dụng window.setTimeout).

Nói chung, đa luồng là rất, rất, rất, rất, rất, rất khó (tôi có nói là khó không?) Để có được quyền, trừ khi bạn đặt thêm các hạn chế (như chỉ sử dụng dữ liệu bất biến).


3

Intel đã thực hiện một số nghiên cứu mã nguồn mở về đa luồng trong Javascript, nó đã được giới thiệu gần đây trên GDC 2012. Đây là liên kết cho video . Nhóm nghiên cứu đã sử dụng OpenCL, chủ yếu tập trung vào các bộ Intel Chip và HĐH Windows. Dự án có tên mã là RiverTrail và mã này có sẵn trên GitHub

Một số liên kết hữu ích hơn:

Xây dựng đường cao tốc tính toán cho các ứng dụng web



1

Đó là các triển khai không hỗ trợ đa luồng. Hiện tại Google Gears đang cung cấp một cách để sử dụng một số hình thức đồng thời bằng cách thực hiện các quy trình bên ngoài nhưng đó là về nó.

Trình duyệt mới mà Google dự kiến ​​sẽ phát hành hôm nay (Google Chrome) thực thi một số mã song song bằng cách tách nó trong quá trình.

Tất nhiên, ngôn ngữ cốt lõi có thể có cùng sự hỗ trợ như Java, nhưng hỗ trợ cho một thứ như đồng thời của Erlang không ở đâu gần đường chân trời.


1

Javascript là một ngôn ngữ đơn luồng. Điều này có nghĩa là nó có một ngăn xếp cuộc gọi và một đống bộ nhớ. Như mong đợi, nó thực thi mã theo thứ tự và phải hoàn thành việc thực thi mã mảnh trước khi chuyển sang mã tiếp theo. Nó đồng bộ, nhưng đôi khi có thể gây hại. Ví dụ, nếu một hàm mất một thời gian để thực thi hoặc phải chờ một cái gì đó, thì nó sẽ đóng băng mọi thứ trong khi đó.


0

Theo như tôi đã nghe thì Google Chrome sẽ có javascript đa luồng, vì vậy đây là một vấn đề "triển khai hiện tại".


0

Nếu không có sự hỗ trợ ngôn ngữ phù hợp cho quá trình đồng bộ hóa luồng, thậm chí sẽ không có ý nghĩa đối với việc triển khai mới để thử. Các ứng dụng JS phức tạp hiện có (ví dụ: mọi thứ sử dụng ExtJS) rất có thể bị sập bất ngờ, nhưng không có synchronizedtừ khóa hoặc thứ gì đó tương tự, sẽ rất khó hoặc thậm chí không thể viết các chương trình mới hoạt động chính xác.


-1

Tuy nhiên, bạn có thể sử dụng chức năng eval để mang lại sự đồng thời cho MỘT SỐ TUYỆT VỜI

/* content of the threads to be run */
var threads = [
        [
            "document.write('Foo <br/>');",
            "document.write('Foo <br/>');",
            "document.write('Foo <br/>');",
            "document.write('Foo <br/>');",
            "document.write('Foo <br/>');",
            "document.write('Foo <br/>');",
            "document.write('Foo <br/>');",
            "document.write('Foo <br/>');",
            "document.write('Foo <br/>');",
            "document.write('Foo <br/>');"
        ],
        [
            "document.write('Bar <br/>');",
            "document.write('Bar <br/>');",
            "document.write('Bar <br/>');",
            "document.write('Bar <br/>');",
            "document.write('Bar <br/>');",
            "document.write('Bar <br/>');",
            "document.write('Bar <br/>');",
            "document.write('Bar <br/>');",
            "document.write('Bar <br/>');"
        ]
    ];

window.onload = function() {
    var lines = 0, quantum = 3, max = 0;

    /* get the longer thread length */
    for(var i=0; i<threads.length; i++) {
        if(max < threads[i].length) {
            max = threads[i].length;
        }
    }

    /* execute them */
    while(lines < max) {
        for(var i=0; i<threads.length; i++) {
            for(var j = lines; j < threads[i].length && j < (lines + quantum); j++) {
                eval(threads[i][j]);
            }
        }
        lines += quantum;
    }
}

-2

Đa luồng với javascript rõ ràng là có thể sử dụng webworkers do HTML5 mang lại.

Sự khác biệt chính giữa webworkers và môi trường đa luồng tiêu chuẩn là tài nguyên bộ nhớ không được chia sẻ với luồng chính, tham chiếu đến một đối tượng không thể nhìn thấy từ luồng này sang luồng khác. Chủ đề giao tiếp bằng cách trao đổi thông điệp, do đó có thể thực hiện thuật toán gọi phương thức đồng bộ hóa và đồng thời theo mẫu thiết kế hướng sự kiện.

Nhiều khung tồn tại cho phép cấu trúc chương trình giữa các luồng, trong số đó có 3MK-JS, khung OOP js hỗ trợ lập trình đồng thời https://github.com/GOMService/oodk-js-oop-for-js


5
Chia sẻ bộ nhớ là định nghĩa chính xác của một Chủ đề trái ngược với một quy trình riêng biệt (ví dụ: fork () so với exec ()). Chủ đề có thể chia sẻ các đối tượng, quá trình phải sử dụng IPC. Công nhân web không phải là đa luồng.
felixfbecker
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.