Em có thể giải thích cho bác về Async như sau
Cái nhìn tổng quát về Async IO
Async IO ít được biết đến hơn so với những thuật ngữ quen thuộc của lập trình cổ điển mà ta đã từng học, thực hành và kiểm nghiệm (
multiprocessing và
threading). Phần này sẽ cung cấp cho bạn bức tranh đầy đủ hơn về async IO (lập trình bất đồng bộ) là gì và cách chúng được sử dụng cho các trường hợp cụ thể.
Async IO được dùng ở đâu
Tính đồng thời (
concurrency) và tính song song (
parallelism) là những topic mở rộng không dễ để tìm hiểu. Mặc dù bài viết này tập trung vào async IO và cách triển khai nó trong Python, nhưng bạn cũng nên dành một phút để so sánh async IO với các “cộng sự của nó” để có được cái nhìn bao quát về cách dùng nó phù hợp trong những bài toán lớn.
parallelism bao gồm việc thực hiện nhiều hành động trong cùng một lúc. Multiprocessing được hiểu là việc thực hiện các tác vụ song song và nó đòi hỏi phải chia sẻ các tác vụ đó cho các đơn vị xử lý trung tâm (cores). Multiprocessing rất phù hợp cho các tác vụ liên quan đến CPU: Như việc thực hiện for-loop hàng loạt và các phép tính toán học thường thuộc loại này.
concurrency là một
thuật ngữ mở rộng của parallelism. Bạn có thể hiểu nó theo nghĩa là một tác vụ có thể chạy thay nhau cùng lúc (cái này chạy một chút rồi đến cái kia chạy một chút - thuật ngữ này gọi là overlapping manner). Và lưu ý rằng đồng thời (concurrency) không có nghĩa là song song (parallelism).
Threading là một mô hình thực thi concurrency mà ở đó nhiều luồng thay phiên nhau thực thi các tác vụ. Một process có thể chứa nhiều thread. Python thực hiện một complicated relationship với threading thông qua GIL, nhưng ta sẽ không nói tới trong bài viết này.
Điều quan trọng cần biết về threading là nó sẽ tốt hơn cho các tác vụ có IO. Trong khi các tác vụ CPU được đặc trưng bởi các core máy tính làm việc liên tục từ đầu đến cuối, thì các tác vụ có liên quan tới IO lại bị chi phối rất nhiều vào thời gian đợi input/output để hoàn thành.
Tóm cái váy lại,
concurrency bao gồm cả
multiprocessing (tốt cho các tác vụ cần CPU) và
threading (cho các tác vụ có IO). Multiprocessing là một dạng parallelism mà ở đó parallelism là tập con của concurrency. Thư viện chuẩn của Python có cung cấp các package multiprocessing, threading và concurrent.futures để hỗ trợ cả hai thứ trên.
Giờ đã đến lúc đưa một thành viên mới vào danh sách này. Trong vài năm qua một thiết kế riêng biệt đã được tích hợp toàn diện hơn vào CPython: asynchronous IO, có thể được gọi thông qua package asyncio trong bộ thư viện chuẩn và các keyword async và await. Để rõ ràng, async IO không phải là một khái niệm mới được phát minh và nó đã tồn tại hoặc đang được tích hợp vào các ngôn ngữ và runtime environment như Go, C#, Scala.
asyncio package được Python documentation ví như là một thư viện để viết code concurrent. Tuy nhiên, async IO không phải là threading, cũng không phải là multiprocessing. Nó không được xây dựng dựa trên hai thứ này.
Thực tế, async IO là một thiết kế single-threaded, single-process: nó sử dụng cooperative multitasking (hợp tác đa nhiệm), một thuật ngữ mà bạn sẽ hiểu rõ khi đọc xong bài này. Nói cách khác async IO mang lại cảm giác như là concurrency (chạy đồng thời) mặc dù sử dụng single-thread trong một single process. Coroutines (một tính năng trung tâm của async IO) có thể được lên lịch đồng thời, nhưng chúng vốn dĩ không đồng thời.
Nhắc lại lần nữa, async IO là một kiểu lập trình concurrent, nhưng nó không phải là parallelism. Nó giống threading hơn là multiprocessing nhưng rất khác biệt so với cả hai thứ này và là một công cụ độc lập trong các công cụ lập trình lập trình concurrency.
Và một thuật ngữ nữa xuất hiện. Nó có nghĩa là gì khi một thứ gì đó bất đồng bộ (asynchronous)? Đây không phải là một định nghĩa cụ thể. Nhưng với mục đích của bài viết này, ta có thể hiểu nó với hai thuộc tính sau:
- Các tiến trình bất đồng bộ có thể “tạm dừng” trong khi chờ đợi kết quả cuối cùng của chúng và để các tiến trình khác chạy trong lúc nó chờ.
- Code bất đồng bộ thông qua cơ chế trên tạo ra một hiệu ứng thực thi đồng thời. Nói cách khác, code bất đồng bộ cho ta cảm giác như nó đang concurrency.
Dưới đây là sơ đồ tổng quát. Các thuật ngữ màu trắng đại diện cho các khái niệm và các thuật ngữ màu xanh lá cây biểu thị các cách thức mà chúng được triển khai hoặc thực hiện:
Ta sẽ dừng lại ở việc so sánh giữa các mô hình lập trình đồng thời. Bài viết này tập trung vào thành phần con của async IO, cách sử dụng chúng và những API có trong nó. Để tìm hiểu thêm về sự khác biệt giữa threading, multiprocessing và async IO, hãy dừng lại ở đây và xem bài viết
tổng quan về concurrency trong Python của Jim Anderson.
Giải thích về Async IO
Async IO thoạt đầu nghe có vẻ vô lý. Làm thế nào mà một thứ gì đó có thể giúp code chạy đồng thời mà chỉ sử dụng một thread và một CPU core? Tôi (tác giả) chưa bao giờ là người giỏi ra ví dụ, vì thế tôi muốn cho các bạn xem một câu từ bài nói chuyện của Miguel Grinberg tại PyCon năm 2017, giải thích mọi thứ khá hay như sau:
Vua cờ Judit Polgár tổ chức một cuộc triển lãm cờ vua trong đó cô ấy chơi với nhiều kỳ thủ nghiệp dư. Cô ấy có hai cách tiến hành: đồng bộ và không đồng bộ.
Giả sử:
- 24 đối thủ
- Judit thực hiện 1 nước cờ trong 5 giây
- Đối thủ thì mất 55 giây để thực hiện một bước
- Một ván trung bình có 30 nước di chuyển đôi (tổng cộng là 60 lần qua lại giữa hai người)
Giải pháp đồng bộ: Judit chơi một ván mỗi lần, không bao giờ chơi hai ván cùng lúc, cho đến khi xong. Mỗi ván mất (55+5) * 30 == 1800 giây, hay 30 phút. Suy ra chơi với toàn bộ 24 người sẽ mất 24 * 30 == 720 phút, hay 12 giờ.
Giải pháp không đồng bộ: Judit chơi từ bàn này sang bàn khác, thực hiện một lần di chuyển trên từng bàn cờ. Nhân lúc đối thủ suy nghĩ để thực hiện bước đi kế tiếp thì trong thời gian đợi đó cô ấy đi qua bàn khác để đi nước tiếp theo. Để thực hiện một lần đi cờ trên cả 24 bàn Judit mất 24 * 5 == 120 giây, hay 2 phút. Suy ra toàn bộ ván cờ cho tất cả 24 bàn cờ sẽ mất 3600 giây, hay 1 giờ.
Chỉ với một Judit Polgar, người chỉ có hai tay và chỉ thực hiện một nước đi mỗi lần. Nhưng bằng cách chơi không đồng bộ đã giúp giảm thời gian của cuộc đấu xuống từ 12 giờ còn 1 giờ. Vì vậy, cooperative multitasking (hợp tác đa nhiệm) là một cách nói fancy ý chỉ về event loop (vòng lặp sự kiện) của chương trình (điều này sẽ nói sau) thực hiện giao tiếp với nhiều task cho phép từng task thay phiên nhau chạy vào những thời điểm rảnh rỗi của CPU.
Trong Async IO, khi một function bị block thì async IO sẽ cho các chương trình khác chạy trong thời gian block đó (một function block những function khác từ khi nó bắt đầu đến khi nó return kết quả - thời gian block đó thường được biết đến với thuật ngữ Độ phức tạp thuật toán).
Trên là trích từ bài dịch của mình khi còn học đại học về Async IO trong Python. Bị Viblo cướp trắng trợn nên cũng hết muốn dịch mà toàn giữ riêng cho mình. Sau khi đi làm được gần 1 năm, bị kêu đi nghĩa vụ nên nghỉ việc dọn về, về thì biết tin dự bị nên quay lại Đà Nẵng Đang thất nghiệp, sẵn tiện ôn bài để đi phỏng vấn thì gặp post của bác. Mong giúp ích.