Lập trình không đồng bộ là một triết lý nhiều hơn là một thủ thuật lập trình khác. Trong khi, câu hỏi cuối cùng của bạn thu hút câu trả lời chủ yếu về các khía cạnh lập trình và câu trả lời của tôi là một người cô đơn bị ngắt kết nối vì chủ yếu là lý thuyết, tôi đang cố gắng cung cấp cho bạn một cách xây dựng phối cảnh mới trên cùng một dòng nhưng giải thích thay vì chỉ tham khảo.
Đây là một số nguyên tắc cơ bản về lý do và cách thức lập trình không đồng bộ.
Giả sử bạn đến một cửa hàng bánh (và giả sử bánh sẽ được chuẩn bị sau khi đặt hàng) - bạn có hai lựa chọn, hoặc bạn chọn đợi cho đến khi bánh sẵn sàng hoặc bạn đặt hàng và quay trở về nhà và nhận sau này khi nó đã sẵn sàng Cái đầu tiên (chờ) là một phương thức đồng bộ và sau đó là phương thức không đồng bộ . Không cần phải nói ví dụ này cung cấp một tài liệu tham khảo tốt tại sao bạn nên sử dụng các phương pháp không đồng bộ trên đồng bộ.
Lập trình dựa trên sự kiện chỉ là một trong những cách mà các hệ thống không đồng bộ có thể được xây dựng và nó không chỉ là một mẫu thiết kế hữu ích mà nó còn là một mẫu kiến trúc. Tôi liệt kê ra các trường hợp lý thuyết này được sử dụng theo cách thực tế hữu ích - hy vọng rằng nó sẽ mang lại sự rõ ràng
Một trong những ví dụ đầu tiên về hệ thống không đồng bộ là hệ thống IO của Unix. Trong khi chúng ta đã biết read()
, write()
và thậm chí select()
gọi khối luồng chương trình, nhưng bên trong hệ điều hành, họ không đồng bộ, tức là hạt nhân nói chung biết rằng thiết bị khối (đĩa aka cứng) sẽ mất một thời gian để đệm điền, cho đến như vậy một thời gian CPU là miễn phí từ luồng tương ứng và do đó luồng được đỗ là (chưa sẵn sàng). Tham khảo 1. Moris Bach "Thiết kế hệ điều hành Unix"
Một ví dụ phổ biến nhất là phần lớn các khung UI. Tại đây, tất cả các lần nhấp của người dùng trước tiên được gửi qua bộ điều khiển, lần lượt gọi lại ứng dụng tương ứng. Điều quan trọng là các cuộc gọi lại như vậy không nên giữ các cuộc gọi lại chờ hệ thống khác sẽ bị đóng băng. Cuộc gọi lại từ bộ điều khiển UI đến back-end thường không đồng bộ nếu chúng liên quan đến xử lý nặng.
Một ví dụ điển hình khác về lập trình không đồng bộ (như một mẫu thiết kế thuần túy) là Active Object. Một đối tượng hoạt động là một đối tượng có luồng riêng của nó để người ta có thể giữ nhiều yêu cầu trong hàng đợi và thực hiện từng cái một. Tham khảo bài viết này: Đối tượng hoạt động . Mẫu này được sử dụng nhiều ngay từ phần mềm Doanh nghiệp đến các khung di động. Các nền tảng phổ biến Java / EJB và .NET cho phép gọi phương thức không đồng bộ cục bộ hoặc từ xa , về cơ bản cho phép các đối tượng bình thường trở thành đối tượng hoạt động. Các đối tượng hoạt động đã có mặt trong Symbian: Các đối tượng hoạt động trong HĐH Symbian của Aapo Haapanen (cũng xem điều này: Các đối tượng hoạt động trong Symbian ). Điều này bây giờ cũng có mặt trongAndroid ).
Ngoài đối tượng Active, cùng tác giả Douglas C. Schmidt , đã sản xuất một số tác phẩm khác tương đương với đối tượng Active và cũng là các mẫu không đồng bộ. Xem Mẫu Xử lý sự kiện này và một tài khoản đầy đủ có sẵn trên cuốn sách Kiến trúc phần mềm hướng mẫu của anh ấy : Các mẫu cho các đối tượng đồng thời và được nối mạng - V2
Khi một đối tượng nhất định cần trả về API, trong khi làm việc ở chế độ nền để thực sự hoàn thành công việc, phương pháp thông thường là có một hệ thống đa luồng để đạt được điều này. Các hệ thống luồng có mặt ở khắp mọi nơi từ C (posix), C ++ ( boost ) đến Java, C #, v.v. Active Object về cơ bản chỉ là một sự trừu tượng có thể che giấu điều này. Xem lý do tại sao triển khai đối tượng hoạt động được ưa thích hơn các chủ đề trần trụi. Một đọc tốt .
Nhưng khái niệm này vượt ra ngoài các luồng hoặc các đối tượng bên trong một ứng dụng để trở nên không đồng bộ. Một trong những cách sử dụng tốt nhất là trong các hệ thống Phân tán, trong đó hai ứng dụng không nhất thiết phải chờ nhau để phối hợp. Tốt cũ (hoặc không tốt lắm, cho dù bạn nhìn nó như thế nào) RPC là đồng bộ. [tất nhiên, cũng có các RPC không đồng bộ khác ]. Nhưng các lựa chọn thay thế hiện đại như Middleware định hướng thư thực sự không đồng bộ vì những lý do chính đáng.
Cuối cùng nhưng có thể thú vị nhất, là chương trình Đại lý có thể hưởng lợi từ mô hình truyền thông không đồng bộ .
Mặc dù lập trình không đồng bộ trông có vẻ gợi cảm nhưng nó tạo ra sự phức tạp của chính nó bao gồm:
- khung để trả lại giá trị
- chi phí truyền thông bổ sung
- cần thêm để đồng bộ hóa các cấu trúc
- khả năng bế tắc, đua xe, vv nếu mọi thứ không được thực hiện đúng.
... và cứ thế.
Nó luôn luôn nên được sử dụng chỉ vì một lý do chính hãng.
Vậy khi nào nên sử dụng mô hình không đồng bộ? Khi nào bạn nên đặt một chủ đề nền và cho phép người gọi đi không đồng bộ? Dưới đây là một số quy tắc ngón tay cái tốt khi áp dụng (nhưng không hoàn thành)
Khi hệ thống muốn áp dụng hội thoại tài nguyên nghiêm ngặt: ví dụ, bạn muốn giữ một số lượng chủ đề cố định tuyệt đối. Mẫu không đồng bộ buộc hệ thống thực hiện hàng đợi.
Khi người gọi cần làm "những việc hữu ích khác để làm" thực sự là chính hãng. Vì vậy, nhiều lần, các chủ đề khác ngay cả khi được thực hiện bỏ chặn, sẽ không làm bất cứ điều gì hữu ích và treo xung quanh bỏ phiếu cho kết quả. Điều này thực sự có thể tiêu thụ CPU nhiều hơn so với mô hình đồng bộ cơ bản.
Khi bạn cần mức độ tin cậy cao hơn trong các hệ thống phân tán. (xem Middleware định hướng tin nhắn ).