Một coroutine là gì? Làm thế nào chúng liên quan đến đồng thời?
Một coroutine là gì? Làm thế nào chúng liên quan đến đồng thời?
Câu trả lời:
Coroutines và concurrency phần lớn là trực giao. Coroutines là một cấu trúc điều khiển chung, theo đó kiểm soát dòng chảy được hợp tác thông qua giữa hai thói quen khác nhau mà không quay trở lại.
Câu lệnh 'suất' trong Python là một ví dụ hay. Nó tạo ra một coroutine. Khi gặp 'năng suất', trạng thái hiện tại của chức năng được lưu và điều khiển được trả về chức năng gọi. Sau đó, chức năng gọi có thể chuyển thực thi trở lại chức năng cho năng suất và trạng thái của nó sẽ được khôi phục đến điểm gặp phải 'năng suất' và việc thực thi sẽ tiếp tục.
Coroutines are a general control structure whereby flow control is cooperatively passed between two different routines without returning.
<- Đây là đồng thời. Từ bạn đang tìm kiếm là song song.
orthogonal = Not similar to each other
?
orthogonal
là "độc lập với nhau".
Từ Lập trình trong Lua , Coroutines
phần "":
Một coroutine tương tự như một luồng (theo nghĩa đa luồng): nó là một dòng thực thi, với ngăn xếp riêng, các biến cục bộ của riêng nó và con trỏ lệnh riêng của nó; nhưng nó chia sẻ các biến toàn cầu và hầu hết mọi thứ khác với các coroutines khác. Sự khác biệt chính giữa các luồng và coroutines là, về mặt khái niệm (hoặc theo nghĩa đen, trong một máy đa bộ xử lý), một chương trình với các luồng chạy một số luồng song song. Mặt khác, các coroutines là hợp tác: tại bất kỳ thời điểm nào, một chương trình với các coroutines chỉ chạy một trong các coroutine của nó, và coroutine này chỉ đình chỉ thực hiện khi nó yêu cầu đình chỉ rõ ràng.
Vì vậy, vấn đề là: Coroutines là "hợp tác". Ngay cả trong hệ thống đa lõi, chỉ có một coroutine chạy tại bất kỳ thời điểm nào (nhưng nhiều luồng có thể chạy song song). Không có sự ngăn chặn giữa các coroutine, coroutine đang chạy phải từ bỏ việc thực hiện một cách rõ ràng.
Đối với " concurrency
", bạn có thể tham khảo slide của Rob Pike :
Đồng thời là thành phần của các tính toán thực thi độc lập.
Vì vậy, trong quá trình hành quyết của coroutine A, nó chuyển giao quyền kiểm soát cho coroutine B. Sau một thời gian, coroutine B chuyển quyền kiểm soát trở lại coroutine A. Vì có sự phụ thuộc giữa các coroutine và chúng phải chạy song song, vì vậy hai coroutine không đồng thời .
Tôi thấy hầu hết các câu trả lời quá kỹ thuật mặc dù đó là một câu hỏi kỹ thuật. Tôi đã có một thời gian khó khăn để cố gắng hiểu quá trình coroutine. Tôi nhận được nó nhưng sau đó tôi không nhận được nó cùng một lúc.
Tôi thấy câu trả lời này ở đây rất hữu ích:
https://dev.to/thibmaek/explain-coroutines-like-im-five-2d9
Để trích dẫn từ Idan Arye:
Để xây dựng câu chuyện của bạn, tôi sẽ đặt nó như thế này:
Bạn bắt đầu xem phim hoạt hình, nhưng đó là phần giới thiệu. Thay vì xem phần giới thiệu, bạn chuyển sang trò chơi và vào sảnh trực tuyến - nhưng nó cần 3 người chơi và chỉ có bạn và em gái của bạn ở trong đó. Thay vì chờ người chơi khác tham gia, bạn chuyển sang bài tập về nhà và trả lời câu hỏi đầu tiên. Câu hỏi thứ hai có liên kết đến video YouTube mà bạn cần xem. Bạn mở nó - và nó bắt đầu tải. Thay vì chờ nó tải, bạn quay lại phim hoạt hình. Phần giới thiệu đã kết thúc, vì vậy bạn có thể xem. Bây giờ có quảng cáo - nhưng trong khi đó, một người chơi thứ ba đã tham gia để bạn chuyển sang trò chơi Và cứ thế ...
Ý tưởng là bạn không chỉ chuyển đổi các nhiệm vụ thực sự nhanh chóng để làm cho nó trông giống như bạn đang làm mọi thứ cùng một lúc. Bạn sử dụng thời gian bạn đang chờ đợi điều gì đó xảy ra (IO) để làm những việc khác đòi hỏi sự chú ý trực tiếp của bạn.
Chắc chắn kiểm tra các liên kết, có nhiều hơn nữa mà tôi không thể trích dẫn tất cả mọi thứ.
Coroutine tương tự như chương trình con / chủ đề. Sự khác biệt là một khi người gọi gọi một chương trình con / luồng, nó sẽ không bao giờ quay trở lại chức năng của người gọi. Nhưng một coroutine có thể quay trở lại người gọi sau khi thực thi một vài đoạn mã cho phép người gọi thực thi một số mã của chính nó và quay trở lại điểm coroutine nơi nó dừng thực thi và tiếp tục từ đó. I E. Một coroutine có nhiều điểm vào và ra
Về cơ bản, có hai loại Coroutines:
Kotlin thực hiện các coroutines stackless - điều đó có nghĩa là các coroutine không có stack riêng, vì vậy chúng không ánh xạ trên luồng gốc.
Đây là các chức năng để bắt đầu coroutine:
launch{}
async{}
Bạn có thể tìm hiểu thêm từ đây:
https://www.kotlindevelopment.com/deep-dive-coroutines/
https://blog.mindork.com/what-are-coroutines-in-kotlin-bf4fecd476e9
Từ Python Coroutine :
Việc thực thi các xác chết Python có thể bị đình chỉ và tiếp tục tại nhiều điểm (xem coroutine). Bên trong phần thân của hàm coroutine, các định danh chờ đợi và không đồng bộ trở thành các từ khóa dành riêng; đang chờ các biểu thức, async for và async with chỉ có thể được sử dụng trong các thân hàm coroutine.
Một coroutine là một chức năng có thể đình chỉ thực hiện để được nối lại sau này . Quân đoàn không có chồng: họ đình chỉ thực hiện bằng cách quay lại người gọi. Điều này cho phép mã tuần tự thực thi không đồng bộ (ví dụ: để xử lý I / O không chặn mà không cần gọi lại rõ ràng) và cũng hỗ trợ các thuật toán trên các chuỗi vô hạn được tính toán lười biếng và các cách sử dụng khác.
So sánh với câu trả lời của người khác:
Theo tôi, phần sau được nối lại là một sự khác biệt cốt lõi, giống như @ Twinkle's.
Mặc dù nhiều lĩnh vực của tài liệu vẫn đang được tiến hành, tuy nhiên, phần này tương tự như hầu hết câu trả lời, ngoại trừ của @Nan Xiao
Mặt khác, các coroutines là hợp tác: tại bất kỳ thời điểm nào, một chương trình với các coroutines chỉ chạy một trong các coroutine của nó, và coroutine này chỉ đình chỉ thực hiện khi nó yêu cầu đình chỉ rõ ràng.
Vì nó được trích dẫn từ Chương trình ở Lua, có thể nó liên quan đến ngôn ngữ (hiện tại không quen thuộc với Lua), nên không phải tất cả tài liệu đều đề cập đến một phần duy nhất .
Mối quan hệ với đồng thời:
Có một phần "Thi hành" của Coroutines (C ++ 20). Xin được trích dẫn ở đây.
Bên cạnh các chi tiết, có một số tiểu bang.
When a coroutine begins execution
When a coroutine reaches a suspension point
When a coroutine reaches the co_return statement
If the coroutine ends with an uncaught exception
When the coroutine state is destroyed either because it terminated via co_return or uncaught exception, or because it was destroyed via its handle
như nhận xét từ @Adam Arold dưới câu trả lời của @ user217714. Đó là sự đồng thời.
Nhưng nó khác với đa luồng.
từ std :: chủ đề
Chủ đề cho phép nhiều chức năng để thực hiện đồng thời. Các luồng bắt đầu thực thi ngay khi xây dựng đối tượng luồng liên quan (đang chờ xử lý bất kỳ độ trễ lập lịch của hệ điều hành), bắt đầu từ hàm cấp cao nhất được cung cấp dưới dạng đối số của hàm tạo. Giá trị trả về của hàm cấp cao nhất bị bỏ qua và nếu nó chấm dứt bằng cách ném một ngoại lệ, std :: terminating được gọi. Hàm cấp cao nhất có thể truyền đạt giá trị trả về của nó hoặc một ngoại lệ cho người gọi thông qua std :: hứa hoặc bằng cách sửa đổi các biến được chia sẻ (có thể yêu cầu đồng bộ hóa, xem std :: mutex và std :: nguyên tử)
Vì nó đồng thời, nó hoạt động như đa luồng, đặc biệt là khi chờ đợi là không thể tránh khỏi (từ góc độ hệ điều hành), đó cũng là lý do khiến nó khó hiểu.
Một coroutine là một loại chương trình con đặc biệt. Thay vì mối quan hệ chủ-chủ giữa người gọi và chương trình con được gọi là tồn tại với các chương trình con thông thường, người gọi và người được gọi là coroutines là công bằng hơn.
Một coroutine là một chương trình con có nhiều mục và tự điều khiển chúng - được hỗ trợ trực tiếp trong Lua
Cũng được gọi là điều khiển đối xứng: người gọi và người được gọi là coroutines trên cơ sở bình đẳng hơn
Một cuộc gọi coroutine được đặt tên là một sơ yếu lý lịch
Sơ yếu lý lịch đầu tiên của một coroutine là bắt đầu, nhưng các cuộc gọi tiếp theo nhập vào điểm ngay sau câu lệnh được thực hiện cuối cùng trong coroutine
Quân đoàn liên tục nối lại nhau, có thể là mãi mãi
Các quân đoàn cung cấp việc thực hiện đồng thời các đơn vị chương trình (các coroutines); thực hiện của họ là xen kẽ, nhưng không chồng chéo
Tôi tìm thấy một lời giải thích từ liên kết này là khá thẳng về phía trước. Không ai trong số những câu trả lời đó cố gắng giải thích sự tương tranh và song song ngoại trừ gạch đầu dòng cuối cùng trong câu trả lời này .
được trích dẫn từ "lập trình Erlang", bởi Joe Armstrong, huyền thoại:
một chương trình đồng thời có thể chạy tiềm năng nhanh hơn trên một máy tính song song.
một chương trình đồng thời là một chương trình được viết bằng ngôn ngữ lập trình đồng thời. Chúng tôi viết các chương trình đồng thời vì lý do hiệu suất, khả năng mở rộng hoặc khả năng chịu lỗi.
một ngôn ngữ lập trình đồng thời là một ngôn ngữ có cấu trúc ngôn ngữ rõ ràng để viết các chương trình đồng thời. Các cấu trúc này là một phần không thể thiếu của ngôn ngữ lập trình và hoạt động theo cùng một cách trên tất cả các hệ điều hành.
một máy tính song song là một máy tính có một số đơn vị xử lý (CPU hoặc lõi) có thể chạy cùng một lúc.
Vì vậy đồng thời không giống như song song. Bạn vẫn có thể viết các chương trình đồng thời trên một máy tính lõi đơn. Bộ lập lịch chia sẻ thời gian sẽ khiến bạn cảm thấy chương trình của mình đang chạy đồng thời.
Chương trình đồng thời có khả năng chạy song song trong một máy tính song song nhưng không được bảo đảm . Hệ điều hành chỉ có thể cung cấp cho bạn một lõi để chạy chương trình của bạn.
Do đó, đồng thời là một mô hình phần mềm từ một chương trình đồng thời không có nghĩa là chương trình của bạn có thể chạy song song về mặt vật lý.
Từ ngữ coroutine nghiêm túc bao gồm hai từ: thói quen (hợp tác) và thói quen trực tuyến (chức năng).
a. nó có đạt được sự tương tranh hay song song không?
Để đơn giản, hãy thảo luận về nó trên một máy tính lõi đơn .
Đồng thời đạt được bằng cách chia sẻ thời gian từ hệ điều hành. Một luồng thực thi mã của nó trong các khung thời gian được chỉ định trên lõi CPU. Nó có thể được hệ điều hành ưu tiên. Nó cũng có thể mang lại quyền kiểm soát cho hệ điều hành.
Mặt khác, một coroutine mang lại quyền kiểm soát cho một coroutine khác trong luồng, không phải cho hệ điều hành. Vì vậy, tất cả các coroutines trong một luồng vẫn khai thác khung thời gian cho luồng đó mà không thu được lõi CPU cho các luồng khác do HĐH quản lý.
Do đó, bạn có thể nghĩ về coroutine đạt được chia sẻ thời gian bởi người dùng không phải bởi hệ điều hành (hoặc bán song song). Các coroutines chạy trên cùng một lõi được gán cho luồng chạy các coroutines đó.
Coroutine có đạt được sự song song không? Nếu đó là mã giới hạn CPU, thì không. Giống như chia sẻ thời gian, nó khiến bạn cảm thấy chúng chạy song song nhưng các lần thực hiện của chúng được xen kẽ không chồng chéo. Nếu nó bị ràng buộc IO, vâng, nó đạt được song song bởi phần cứng (thiết bị IO) không phải bởi mã của bạn.
b. sự khác biệt với chức năng gọi?
Như pic cho thấy, nó không cần phải gọi return
để chuyển đổi điều khiển. Nó có thể mang lại mà không có return
. Một coroutine lưu và chia sẻ trạng thái trên khung chức năng hiện tại (ngăn xếp). Vì vậy, nó nhẹ hơn nhiều so với chức năng vì bạn không phải lưu các thanh ghi và biến cục bộ để xếp chồng và tua lại ngăn xếp cuộc gọi khi call ret
.
Tôi sẽ mở rộng câu trả lời của @ user21714. Quân đoàn là những con đường thực thi độc lập không thể chạy đồng thời. Chúng phụ thuộc vào bộ điều khiển - ví dụ python
thư viện bộ điều khiển - để xử lý chuyển đổi giữa các đường dẫn này. Nhưng để làm việc này, các coroutines cần phải gọi yield
hoặc các cấu trúc tương tự cho phép tạm dừng thực thi.
Thay vào đó, các luồng đang chạy trên các tài nguyên tính toán độc lập và song song với nhau. Vì chúng ở trên các tài nguyên khác nhau, không cần phải gọi năng suất để cho phép các đường dẫn thực hiện khác được tiến hành.
Bạn có thể thấy hiệu ứng này bằng cách bắt đầu một chương trình đa luồng - ví dụ: một jvm
ứng dụng - trong đó tất cả tám core i7
lõi siêu phân luồng của bạn được sử dụng: bạn có thể thấy mức sử dụng 797% trong Activity Monitor
hoặc Top
. Thay vào đó khi chạy một python
chương trình thông thường - thậm chí một chương trình có coroutines
hoặc python threading
- việc sử dụng sẽ đạt tối đa 100%. Tức là một siêu máy.