2008-09-24 39 views
87

Tôi đã thấy liên kết này: Implementing Mutual Exclusion in JavaScript. Mặt khác, tôi đã đọc rằng không có luồng trong javascript, nhưng chính xác thì điều đó có nghĩa là gì?Mutexes có cần thiết trong javascript không?

Khi sự kiện xảy ra, bạn có thể làm gián đoạn mã nào trong mã?

Và nếu không có chủ đề nào trong JS, tôi có cần sử dụng mutex trong JS hay không?

Cụ thể, tôi tự hỏi về tác động của việc sử dụng các hàm được gọi là setTimeout() và trên các biến có thể truy cập trên toàn cầu.

+1

Nope, không mutex hoặc bất kỳ công cụ kiểm soát đồng thời khác trong javascript. Xem [Tại sao không có công cụ kiểm soát đồng thời trong javascript] (http://uzairfarooq.github.io/why-no-concurrency-control-tool-in-javascript/). –

Trả lời

87

Javascript được định nghĩa là một reentrant ngôn ngữ đó có nghĩa là có không có luồng tiếp xúc với người dùng, có thể có các chủ đề trong quá trình thực hiện. Các hàm như setTimeout() và các cuộc gọi lại không đồng bộ cần phải đợi cho công cụ tập lệnh ngủ trước khi chúng có thể chạy.

Điều đó có nghĩa là mọi thứ xảy ra trong sự kiện phải được hoàn tất trước khi sự kiện tiếp theo được xử lý.

Điều đó đang được nói, bạn có thể cần một mutex nếu mã của bạn làm điều gì đó mà nó mong đợi giá trị không thay đổi giữa khi sự kiện không đồng bộ được kích hoạt và khi gọi lại. Ví dụ: nếu bạn có cấu trúc dữ liệu nơi bạn nhấp vào một nút và nó sẽ gửi XmlHttpRequest gọi hàm gọi lại, thay đổi cấu trúc dữ liệu theo cách phá hoại và bạn có một nút khác thay đổi cấu trúc dữ liệu tương tự trực tiếp, giữa khi sự kiện này được kích hoạt và khi cuộc gọi lại được thực thi, người dùng có thể đã nhấp và cập nhật cấu trúc dữ liệu trước khi gọi lại mà sau đó có thể mất giá trị.

Trong khi bạn có thể tạo điều kiện cuộc đua như thế thì rất dễ để ngăn điều đó trong mã của bạn vì mỗi hàm sẽ là nguyên tử. Nó sẽ là rất nhiều công việc và có một số mẫu mã hóa kỳ lạ để tạo ra các điều kiện chủng tộc trong thực tế.

+1

Không khó để tạo điều kiện chủng tộc này: ví dụ, tôi có sự kiện "onkeyup" trong một trường, kích hoạt cuộc gọi ajax đến DB để nhận một số giá trị. Nhanh chóng nhập dữ liệu có thể dễ dàng dẫn đến kết quả không theo thứ tự. – thomasb

5

JavaScript là chuỗi đơn ... mặc dù Chrome có thể là một con thú mới (tôi nghĩ nó cũng là một chuỗi duy nhất, nhưng mỗi tab có chuỗi JavaScript riêng ... Tôi chưa xem xét chi tiết, vì vậy đừng không báo cho tôi ở đó).

Tuy nhiên, một điều bạn cần phải lo lắng là làm thế nào JavaScript của bạn sẽ xử lý nhiều yêu cầu ajax quay lại không theo cùng thứ tự bạn gửi cho chúng. Vì vậy, tất cả các bạn thực sự cần phải lo lắng về là đảm bảo cuộc gọi ajax của bạn được xử lý theo cách mà họ sẽ không bước vào chân của eachother nếu kết quả trở lại theo thứ tự khác với bạn gửi cho họ.

này đi cho timeouts quá ...

Khi Javascript phát triển đa luồng, thì có lẽ lo lắng về mutexes và những thứ tương tự ....

1

Sự kiện được báo hiệu, nhưng thực thi JavaScript vẫn là một luồng.

Sự hiểu biết của tôi là khi sự kiện được báo hiệu, công cụ sẽ dừng những gì nó đang thực hiện vào lúc này để chạy trình xử lý sự kiện. Sau khi trình xử lý kết thúc, việc thực thi tập lệnh được tiếp tục. Nếu trình xử lý sự kiện đã thay đổi một số biến được chia sẻ thì mã được tiếp tục sẽ thấy những thay đổi này xuất hiện "ngoài màu xanh".

Nếu bạn muốn "bảo vệ" dữ liệu được chia sẻ, cờ boolean đơn giản phải là đủ.

1

JavaScript, các ngôn ngữ, có thể được như đa luồng như bạn muốn, nhưng embeddings trình duyệt của động cơ javascript chỉ chạy một callback (onload, onfocus, < kịch bản >, vv ...) tại một thời điểm (mỗi tab , có lẽ). Đề xuất của William về việc sử dụng Mutex cho những thay đổi giữa đăng ký và nhận cuộc gọi lại không nên được thực hiện theo nghĩa đen bởi vì điều này, vì bạn sẽ không muốn chặn cuộc gọi lại can thiệp vì cuộc gọi lại sẽ mở khóa sẽ bị chặn sau cuộc gọi lại hiện tại ! (Wow, tiếng Anh hút để nói về luồng.) Trong trường hợp này, bạn có thể muốn làm một cái gì đó dọc theo dòng redispatching sự kiện hiện tại nếu một lá cờ được thiết lập, hoặc theo nghĩa đen hoặc với những thích của setTimeout().

Nếu bạn đang sử dụng tính năng nhúng JS khác nhau và thực thi nhiều luồng cùng một lúc, nó có thể bị xáo trộn hơn một chút, nhưng do cách JS có thể sử dụng gọi lại dễ dàng và khóa các đối tượng truy cập thuộc tính rõ ràng là gần như không cần thiết. Tuy nhiên, tôi sẽ ngạc nhiên nếu một nhúng được thiết kế cho mã chung (ví dụ, kịch bản trò chơi) mà sử dụng đa luồng cũng không cung cấp cho một số nguyên thủy khóa rõ ràng là tốt.

Xin lỗi vì tường văn bản!

15

Câu trả lời cho câu hỏi này hơi lỗi thời mặc dù đã chính xác vào thời điểm chúng được đưa ra. Và vẫn chính xác nếu nhìn vào một ứng dụng javascript phía máy khách mà KHÔNG sử dụng webworkers.

Các bài viết về web nghiệp:
multithreading in javascript using webworkers
Mozilla on webworkers

Điều này cho thấy rõ ràng rằng javascript qua web-công nhân có khả năng xử lý đa luồng. Liên quan đến câu hỏi là mutexes cần thiết trong javascript? Tôi không chắc chắn về điều này. Nhưng stackoverflow bài này dường như có liên quan:
Mutual Exclusion for N Asynchronous Threads

+2

vụ nổ từ quá khứ, nhưng tôi gặp phải nhu cầu về mutexes khi nhiều tab truy cập cùng một bộ nhớ cục bộ – psp

+1

WebWorkers không ảnh hưởng đến quyền truy cập lại vì chúng không chia sẻ trạng thái biến và chỉ giao tiếp với chủ đề chính bằng cách truyền thông điệp. . – Alnitak

9

Như @william chỉ ra,

bạn có thể cần một mutex nếu mã của bạn làm điều gì đó mà họ hy vọng một giá trị không thay đổi giữa khi sự kiện không đồng bộ đã bị sa thải và khi cuộc gọi lại được gọi.

Điều này có thể được khái quát hơn - nếu mã của bạn thực hiện điều gì đó mà nó muốn kiểm soát độc quyền tài nguyên cho đến khi yêu cầu không đồng bộ được giải quyết, bạn có thể cần một mutex.

Ví dụ đơn giản là nơi bạn có nút kích hoạt cuộc gọi ajax để tạo bản ghi ở phần cuối. Bạn có thể cần một chút mã để bảo vệ bạn khỏi kích hoạt người dùng hạnh phúc khi nhấp chuột và từ đó tạo nhiều bản ghi. có một số phương pháp tiếp cận cho vấn đề này (ví dụ: tắt nút, bật thành công ajax). Bạn cũng có thể sử dụng một khóa đơn giản:

var save_lock = false; 
$('#save_button').click(function(){ 
    if(!save_lock){ 
     //lock 
     save_lock=true; 
     $.ajax({ 
      success:function() 
       //unlock 
       save_lock = false; 
      } 
     }); 
    } 
} 

Tôi không chắc chắn nếu đó là phương pháp tốt nhất và tôi sẽ được quan tâm để xem cách người khác xử lý loại trừ lẫn nhau trong javascript, nhưng như xa như tôi biết đó là một mutex đơn giản và nó rất tiện dụng.

+3

Tôi hầu như không gọi đây là một mutex, ít nhất là không theo nghĩa truyền thống, bởi vì bạn không có hai luồng chạy trong ngữ cảnh của một khối duy nhất bất cứ lúc nào. – Ovesh

+7

một mutex chỉ đơn giản là một thuật toán giúp 'tránh việc sử dụng đồng thời một tài nguyên chung'. Mặc dù đa luồng tạo ra một nhu cầu cho mutexes, không có gì trong định nghĩa nói rằng một mutex là cụ thể cho tình hình bạn mô tả. – alzclarke

+1

Bạn chính xác về định nghĩa chính thức của mutex. Nhưng điều này hầu như không phải là những gì mọi người nghĩ về khi họ nói về mutexes trong thế giới thực. – Ovesh

1

Có, có thể yêu cầu mutex trong Javascript khi truy cập tài nguyên được chia sẻ giữa các tab/cửa sổ, như localStorage.

Ví dụ, nếu người dùng có hai tab mở, mã đơn giản như sau đây là không an toàn:

function appendToList(item) { 
    var list = localStorage["myKey"]; 
    if (list) { 
     list += "," + item; 
    } 
    else { 
     list = item; 
    } 
    localStorage["myKey"] = list; 
} 

Giữa thời điểm đó mục localStorage là 'có' và 'đặt', tab khác có thể có đã sửa đổi giá trị. Nó thường không, nhưng có thể - bạn cần phải đánh giá cho mình khả năng và rủi ro liên quan đến bất kỳ tranh chấp trong hoàn cảnh cụ thể của bạn.

Xem các bài viết sau đây để biết một chi tiết hơn:

Các vấn đề liên quan