Trang chủ » Mã hóa » Giới thiệu về Bộ nhớ dùng chung trong JavaScript

    Giới thiệu về Bộ nhớ dùng chung trong JavaScript

    Bộ nhớ dùng chung là một tính năng nâng cao của JavaScript, các luồng (các phần được thực hiện đồng thời của một tiến trình) có thể tận dụng. Chia sẻ bộ nhớ có nghĩa là không gặp sự cố khi truyền dữ liệu cập nhật giữa các luồng và tất cả các luồng có thể truy cập và cập nhật cùng một dữ liệu trong bộ nhớ dùng chung.

    Nghe có vẻ đáng yêu phải không? Vâng, gần như vậy. Trong bài viết này, chúng ta sẽ thấy Cách sử dụng bộ nhớ dùng chung trong JavaScript và làm thế nào để quyết định nếu đây là những gì bạn thực sự muốn làm.

    Ưu điểm & nhược điểm của bộ nhớ dùng chung

    Chúng tôi sử dụng nhân viên web đến tạo chủ đề trong JavaScript. API công nhân web cho phép chúng tôi tạo các luồng công nhân có thể được sử dụng để thực thi mã trong nền để luồng chính được tự do tiếp tục thực thi, có thể xử lý các sự kiện UI, đảm bảo không bị đóng băng UI.

    Chủ đề công nhân chạy đồng thời với luồng chính và nhau. Việc thực hiện đồng thời các phần khác nhau của một nhiệm vụ là tiết kiệm thời gian. Bạn hoàn thành nhanh hơn, nhưng nó cũng có vấn đề riêng của nó.

    Đảm bảo rằng mỗi chủ đề có được các nguồn lực cần thiết và liên lạc với nhau một cách kịp thời là một nhiệm vụ trong chính nó, trong đó một rủi ro có thể dẫn đến một kết quả đáng ngạc nhiên. Hoặc nếu một luồng đang thay đổi dữ liệu và một luồng khác đang đọc nó cùng một lúc, Bạn nghĩ chủ đề khác sẽ thấy gì? Dữ liệu cập nhật hoặc cũ?

    Tuy nhiên, nhân viên web không dễ dàng để bắt vít. Trong quá trình liên lạc của họ thông qua việc sử dụng tin nhắn, dữ liệu họ gửi cho nhau là không phải bản gốc mà là bản sao, nghĩa là họ không chia sẻ cùng một dữ liệu. Họ truyền các bản sao dữ liệu cho nhau Khi cần thiết.

    Nhưng chia sẻ là quan tâm và nhiều chủ đề cũng có thể cần phải xem cùng một dữ liệu cùng một lúc và thay đổi chúng. Vì thế, cấm chia sẻ là một điều không nên. Đây là nơi SharedArrayBuffer đối tượng đi vào hình ảnh. Nó sẽ cho chúng tôi chia sẻ dữ liệu nhị phân giữa nhiều luồng.

    Các SharedArrayBuffer vật

    Thay vì chuyển các bản sao dữ liệu giữa các luồng, chúng tôi vượt qua các bản sao của SharedArrayBuffer vật. Một SharedArrayBuffer vật chỉ vào bộ nhớ nơi lưu dữ liệu.

    Vì vậy, ngay cả khi các bản sao của SharedArrayBuffer được truyền giữa các chủ đề, họ tất cả vẫn sẽ chỉ về cùng một bộ nhớ nơi dữ liệu gốc được lưu. Các chủ đề, do đó, có thể xem và cập nhật dữ liệu trong cùng bộ nhớ.

    Nhân viên web không có bộ nhớ chia sẻ

    Để xem cách một nhân viên web làm việc mà không sử dụng bộ nhớ dùng chung, chúng tôi tạo một luồng công nhânchuyển một số dữ liệu cho nó.

    Các index.html tập tin giữ kịch bản chính bên trong như bạn có thể thấy nó bên dưới:

     const w = Công nhân mới ('worker.js'); var n = 9; w.postMessage (n); 

    Các worker.js tập tin mang kịch bản công nhân:

     onmessage = (e) => console.group ('[worker]'); console.log ('Dữ liệu nhận được từ luồng chính:% i', e.data); console.groupEnd ();  

    Sử dụng mã ở trên, chúng tôi nhận được sau đây đầu ra trong giao diện điều khiển:

     [worker] Dữ liệu nhận được từ luồng chính: 9 

    Bạn có thể đọc bài viết đã nói ở trên của tôi về nhân viên web để được giải thích đầy đủ về mã của các đoạn trên.

    Bây giờ, hãy nhớ rằng dữ liệu là gửi qua lại giữa các chủ đề sử dụng postMessage () phương pháp. Dữ liệu là nhận được ở phía bên kia của thông điệp xử lý sự kiện, như giá trị của sự kiện dữ liệu bất động sản.

    Bây giờ, nếu chúng ta thay đổi dữ liệu nó sẽ xuất hiện cập nhật ở cuối nhận? Hãy xem:

     const w = Công nhân mới ('worker.js'); var n = 9; w.postMessage (n); n = 1; 

    Như mong đợi, dữ liệu có không phải đã được cập nhật:

     [worker] Dữ liệu nhận được từ luồng chính: 9 

    Tại sao nó sẽ, dù sao? nó là chỉ là một bản sao được gửi đến công nhân từ kịch bản chính.

    Nhân viên web với bộ nhớ chia sẻ

    Bây giờ, chúng tôi sẽ sử dụng SharedArrayBuffer vật trong cùng một ví dụ Chúng ta có thể tạo một cái mới SharedArrayBuffer ví dụ bởi sử dụng Mới từ khóa. Hàm tạo lấy một tham số; một giá trị độ dài tính bằng byte, Chỉ định kích thước của bộ đệm.

     const w = Công nhân mới ('worker.js'); buff = SharedArrayBuffer mới (1); var Array = new Int8Array (buff); / * cài đặt dữ liệu * / Array [0] = 9; / * gửi bộ đệm (bản sao) cho worker * / w.postMessage (buff); 

    Lưu ý rằng một SharedArrayBuffer vật chỉ đại diện cho một vùng bộ nhớ dùng chung. Đến xem và thay đổi dữ liệu nhị phân, chúng ta cần sử dụng một cấu trúc dữ liệu phù hợp (a TypedArray hoặc một Xem dữ liệu vật).

    bên trong index.html tập tin ở trên, một cái mới SharedArrayBuffer được tạo ra, chỉ với độ dài một byte. Sau đó, một cái mới Int8Array, đó là một loại TypedArray đối tượng, được sử dụng để đặt dữ liệu thành “9” trong không gian byte được cung cấp.

     onmessage = (e) => var Array = new Int8Array (e.data); console.group ('[worker]'); console.log ('Dữ liệu nhận được từ luồng chính:% i', Array [0]); console.groupEnd ();  

    Int8Array cũng được sử dụng trong công nhân, để xem dữ liệu trong bộ đệm.

    Các giá trị mong đợi xuất hiện trong giao diện điều khiển từ luồng công nhân, đó chính xác là những gì chúng ta muốn:

     [worker] Dữ liệu nhận được từ luồng chính: 9 

    Bây giờ chúng ta hãy cập nhật dữ liệu trong luồng chính để xem sự thay đổi được phản ánh trong công nhân.

     const w = new Worker ('worker.js'), buff = new SharedArrayBuffer (1); var Array = new Int8Array (buff); / * cài đặt dữ liệu * / Array [0] = 9; / * gửi bộ đệm (bản sao) cho worker * / w.postMessage (buff); / * thay đổi dữ liệu * / Array [0] = 1;

    Và, như bạn có thể thấy bên dưới, bản cập nhật không phản ánh bên trong công nhân!

     [worker] Dữ liệu nhận được từ luồng chính: 1 

    Nhưng, mã cũng cần phải làm việc theo cách khác: khi giá trị trong worker thay đổi lúc đầu, nó cũng cần được cập nhật khi nó được in từ chủ đề chính.

    Trong trường hợp này, mã của chúng tôi trông như thế này:

     onmessage = (e) => var Array = new Int8Array (e.data); console.group ('[worker]'); console.log ('Dữ liệu nhận được từ luồng chính:% i', Array [0]); console.groupEnd (); / * thay đổi dữ liệu * / Array [0] = 7; / * đăng lên chủ đề chính * / postMessage ("); 

    Các dữ liệu được thay đổi trong công nhân và một tin nhắn trống được gửi đến chủ đề chính báo hiệu rằng dữ liệu trong bộ đệm đã được thay đổi và sẵn sàng cho luồng chính được xuất ra.

     const w = new Worker ('worker.js'), buff = new SharedArrayBuffer (1); var Array = new Int8Array (buff); / * cài đặt dữ liệu * / Array [0] = 9; / * gửi bộ đệm (bản sao) cho worker * / w.postMessage (buff); / * thay đổi dữ liệu * / Array [0] = 1; / * in dữ liệu sau khi công nhân đã thay đổi nó * / w.onmessage = (e) => console.group ('[main]'); console.log ('Dữ liệu cập nhật nhận được từ luồng công nhân:% i', Array [0]); console.groupEnd ();  

    Và, điều này cũng hoạt động! Dữ liệu trong bộ đệm giống như dữ liệu bên trong worker.

     [worker] Dữ liệu nhận được từ luồng chính: 1 [main] Dữ liệu cập nhật nhận được từ luồng worker: 7 

    Giá trị xuất hiện cập nhật trong cả hai trường hợp; cả luồng chính và luồng worker đều đang xem và thay đổi cùng một dữ liệu.

    Từ cuối cùng

    Như tôi đã đề cập trước đó, sử dụng bộ nhớ dùng chung trong JavaScript không phải là không có nhược điểm. Tùy thuộc vào các nhà phát triển để đảm bảo rằng trình tự thực hiện xảy ra như dự đoán và không có hai chủ đề đang chạy đua để có được cùng một dữ liệu vì không ai biết ai sẽ nhận cúp.

    Nếu bạn quan tâm đến bộ nhớ chia sẻ nhiều hơn, hãy xem tài liệu của Nguyên tử vật. Các Đối tượng nguyên tử có thể giúp bạn với một số khó khăn, bằng cách giảm tính không thể đoán trước của việc đọc / ghi từ bộ nhớ dùng chung.