Mọi người xây dựng vòng lặp sự kiện để hiểu và mô tả nó hoạt động như thế nào. Điều đó thật tuyệt. Tôi cũng muốn hiểu nó. Vì vậy, tôi quyết định làm một cái… Một cái giả… Như mọi người vẫn làm… Nhưng điều tôi muốn chỉ ra — đó là hàng giả
Vòng lặp sự kiện là gì?
Vòng lặp sự kiện là một cấu trúc lập trình được xử lý tự do và là công cụ đầu mối cho chính chương trình co-op và đồng thời. Nhưng nó phát triển đúng nghĩa khi nó được sử dụng để xây dựng các chương trình không đồng bộ. Vì lý do đó, tôi coi bất kỳ dạng vòng lặp sự kiện nào không thể được sử dụng để xây dựng sự không đồng bộ - giả mạo
Vòng lặp sự kiện chờ và gửi các sự kiện hoặc thông báo trong một chương trình. Nó hoạt động bằng cách gửi yêu cầu tới một số “nhà cung cấp sự kiện” bên trong hoặc bên ngoài [thường chặn yêu cầu cho đến khi một sự kiện đến], sau đó nó gọi trình xử lý sự kiện có liên quan [“gửi sự kiện”]
Vòng lặp sự kiện là một giải pháp cho một vấn đề logic cổ điển “Các nhà triết học ăn uống”
Năm triết gia im lặng ngồi quanh chiếc bàn tròn với bát mì spaghetti. Dĩa được đặt giữa mỗi cặp triết gia liền kề
Mỗi triết gia phải luân phiên nghĩ và ăn. Tuy nhiên, một triết gia chỉ có thể ăn spaghetti khi họ có cả nĩa trái và nĩa phải. Mỗi chiếc nĩa chỉ có thể được giữ bởi một triết gia và vì vậy một triết gia chỉ có thể sử dụng chiếc nĩa nếu nó không được sử dụng bởi một triết gia khác. Sau khi một triết gia cá nhân ăn xong, họ cần đặt cả hai chiếc nĩa xuống để những chiếc nĩa đó dành cho người khác
Vòng lặp sự kiện đồng tình với một phần thứ tự thu được tài nguyên được chia sẻ và gửi sự kiện. Trong vấn đề, các nhánh được chia sẻ tài nguyên, các nhà triết học đang thu thập các quy trình, cảm giác no và mong muốn suy nghĩ là các sự kiện được sử dụng để đồng tình và cân bằng việc sử dụng tài nguyên
vòng lặp chính xác
Dưới đây là một vòng lặp sự kiện. Nó có thể giúp hiểu mức độ không đồng bộ có thể xảy ra nhưng ở trạng thái hiện tại, nó không thể thực hiện được
tasks = {"-=* BOOM *=-": 2, "~=* shaka *=~": 1}
nhiệm vụ. Trong các tác vụ vòng lặp sự kiện thực được tạo từ các sự kiện/thông báo đến từ quy trình bên ngoài. Trong triển khai giả, các tác vụ là hằng số và được trình bày mãi mãi bên trong vòng lặp
if not in_action:
in_action = [
coro[sound, delay] for sound, delay in tasks.items[]
]
Các tác vụ thực tế sẽ được xử lý trong vòng lặp sự kiện. Các nhiệm vụ gần như có thật từ quan điểm đó. Một tác vụ sẽ được xử lý tương ứng với các sự kiện mà nó tạo ra. Bản thân vòng lặp không quan tâm đến tính toán trong các nhiệm vụ hoặc mối quan hệ của nhiệm vụ với thế giới bên ngoài, nó chỉ quan tâm đến các sự kiện. Một sự khác biệt là trong thực hiện nhiệm vụ
task = in_action.pop[0]
Nhận nhiệm vụ để xử lý. Trong vòng lặp cụ thể này, tôi nhận nhiệm vụ tiếp theo một cách mù quáng. Trong chương trình thực, chúng ta có thể có thông tin bổ sung về các sự kiện trước đó và ví dụ: xử lý các tác vụ bằng cách sử dụng dữ liệu này. Không có sự khác biệt chính
dl = task.send[None]
nhiệm vụ thức. Dòng này kết hợp một số mục đích. Lúc đầu, đây là lệnh gọi trình xử lý tác vụ dẫn đến kết quả tính toán tác vụ cuối cùng. Ngoài ra, nó nhận được một phần kết quả tính toán ở mỗi lần lặp. Và cuối cùng là xử lý sự kiện task. Chúng tôi có hai sự kiện 'sẵn sàng' và 'đang diễn ra'. Khi một tác vụ đang được tiến hành, chỉ có kết quả trung gian [dữ liệu meta] sẽ được lấy từ đối tượng có thể chờ đợi. Nếu tác vụ 'sẵn sàng' thì lỗi StopIteration
sẽ xuất hiện và giá trị kết quả sẽ có sẵn trong đó. Trong triển khai giả mạo của chúng tôi, không có tính toán nào tồn tại đằng sau tác vụ. Kết quả tính toán trung gian chỉ được sử dụng để duy trì quá trình tạo tác vụ vô hạn [độ trễ ban đầu được sử dụng để tạo tác vụ tương tự khi tác vụ được thực hiện]. Hệ thống sự kiện cũng được đơn giản hóa — “sẵn sàng” và “đang tiến hành” có thể là không đủ, mỗi phép tính trung gian có thể mang lại các sự kiện khác nhau
in_action.append[coro[e.value, tasks[e.value]]]
Vòng lặp là vô hạn nên một nhiệm vụ mới có cùng đối số sẽ được thêm vào khi hoàn thành một nhiệm vụ
in_action.append[task]
Đưa các nhiệm vụ “đang tiến hành” trở lại vòng lặp
Sự khác biệt đầu mối
coro
coroutine đang đợi từ một thể hiện của đối tượng có thể chờ đợi của Delay
. Không có tính toán. Ngoài ra, đường ống không giao tiếp với các quy trình bên ngoài. Nhưng cả hai bước của quy trình đều cẩn thận giả vờ không đồng bộ bằng cách sử dụng tính năng chính của coroutines - trạng thái tạm dừng. Chuỗi hệ điều hành là tài nguyên được chia sẻ cho tất cả các tác vụ đã bắt đầu. Vì vậy, nếu để thực hiện bất kỳ tính toán nào [thao tác chặn] bên trong các tác vụ, nó sẽ mất chính xác thời gian như nhau bất kể nó được thực hiện theo thứ tự nghiêm ngặt hay theo thứ tự một phần. Tổng là như nhau bất kể bạn nhóm các số như thế nào. Nó có vô ích không? . Không nếu thời gian giữa các lần nhận được kết quả cuối cùng là quan trọng
Hiểu về sự không đồng bộ
Trong vòng lặp, chúng tôi đã không triển khai tính không đồng bộ thực sự [hữu ích] nhưng có sự đồng thời giúp chúng tôi hiểu cách thức hoạt động của tính không đồng bộ
Chúng tôi đang trả tiền với thời gian ở đây. Và thời gian là chung cho mỗi nhiệm vụ trong vòng lặp. Xác định độ trễ theo số tuyệt đối [giây] cho mỗi tác vụ, chúng ta có thể thao tác với các tác vụ tương ứng với thời điểm hiện tại vì cả hai bước của đường ống đều có thể tạm dừng trạng thái của nó. Phiên bản Delay
sẽ được lưu giữ trong coro
cho đến khi coro
trả lại. Thời gian của sự kiện 'sẵn sàng' sẽ được giữ bởi đối tượng có thể chờ đợi của Delay
cho đến khi nó trở thành hiện thực. Vì vậy, mỗi nhiệm vụ đã dành chính xác thời gian nhất định [trong đối số
if not in_action:
in_action = [
coro[sound, delay] for sound, delay in tasks.items[]
]
3] để chờ đợi nhưng các nhiệm vụ đã dành những khoảng thời gian này đồng thời nhưng không mạch lạcVì vậy, đây là sự không đồng bộ giữa nhiệm vụ và thời gian. Thời gian là chung, khách quan và tạo ra các sự kiện cho các nhiệm vụ
Điều gì còn thiếu để triển khai tính không đồng bộ hữu ích?
- Thao tác chặn phải được thực hiện trong [các] quy trình khác nhau. Đây là sự không đồng bộ giữa bộ lập lịch tác vụ co-op và các quy trình tính toán độc lập [theo nghĩa rộng]
- Các sự kiện từ các quy trình này phải được cung cấp bằng cách sử dụng các công cụ liên lạc giữa các quy trình — non-blocking sockets
- Ngoài ra, các tác vụ có thể được cung cấp bởi nguồn sự kiện/tin nhắn bên ngoài vòng lặp. [Mô hình lò phản ứng]
Phần kết luận
Thật tốt khi hiểu đồng thời và không đồng bộ bằng các ví dụ thực tế đơn giản. Nhưng đừng tin vào sự cường điệu, các chương trình không đồng bộ thực sự phức tạp hơn và sử dụng nhiều công cụ hơn vòng lặp sự kiện trần. Mặc dù sự hiểu biết về bản chất hợp tác của vòng lặp sự kiện làm cho sự hiểu biết về sự không đồng bộ trở thành một kết quả thấp