Sự khác biệt giữa một sợi và sợi là gì? Tôi đã nghe nói về các sợi từ ruby và tôi đã đọc được rằng chúng có sẵn bằng các ngôn ngữ khác, ai đó có thể giải thích cho tôi bằng những thuật ngữ đơn giản về sự khác biệt giữa một sợi và sợi.
Sự khác biệt giữa một sợi và sợi là gì? Tôi đã nghe nói về các sợi từ ruby và tôi đã đọc được rằng chúng có sẵn bằng các ngôn ngữ khác, ai đó có thể giải thích cho tôi bằng những thuật ngữ đơn giản về sự khác biệt giữa một sợi và sợi.
Câu trả lời:
Nói một cách đơn giản nhất, các luồng thường được coi là có khả năng ngăn chặn (mặc dù điều này có thể không phải lúc nào cũng đúng, tùy thuộc vào hệ điều hành) trong khi các sợi được coi là các sợi nhẹ, hợp tác. Cả hai đều là đường dẫn thực thi riêng cho ứng dụng của bạn.
Với các luồng: đường dẫn thực thi hiện tại có thể bị gián đoạn hoặc bị chặn bất cứ lúc nào (lưu ý: tuyên bố này là một khái quát và có thể không luôn luôn đúng tùy thuộc vào hệ điều hành / gói luồng / v.v.). Điều này có nghĩa là đối với các luồng, tính toàn vẹn dữ liệu là một vấn đề lớn vì một luồng có thể bị dừng ở giữa quá trình cập nhật một đoạn dữ liệu, khiến tính toàn vẹn của dữ liệu ở trạng thái xấu hoặc không đầy đủ. Điều này cũng có nghĩa là hệ điều hành có thể tận dụng nhiều CPU và lõi CPU bằng cách chạy nhiều hơn một luồng cùng lúc và để cho nhà phát triển bảo vệ quyền truy cập dữ liệu.
Với các sợi: đường dẫn thực hiện hiện tại chỉ bị gián đoạn khi sợi mang lại sự thực thi (cùng lưu ý như trên). Điều này có nghĩa là các sợi luôn bắt đầu và dừng ở những nơi được xác định rõ, do đó tính toàn vẹn dữ liệu ít xảy ra hơn. Ngoài ra, do các sợi thường được quản lý trong không gian người dùng, các chuyển đổi ngữ cảnh đắt tiền và thay đổi trạng thái CPU không cần phải thực hiện, việc thay đổi từ sợi này sang sợi tiếp theo cực kỳ hiệu quả. Mặt khác, vì không có hai sợi nào có thể chạy cùng một lúc, nên chỉ sử dụng các sợi sẽ không tận dụng được nhiều CPU hoặc nhiều lõi CPU.
Chủ đề sử dụng pre-emptive lịch trình, trong khi sợi sử dụng hợp tác lập kế hoạch.
Với một luồng, luồng điều khiển có thể bị gián đoạn bất cứ lúc nào và luồng khác có thể chiếm quyền điều khiển. Với nhiều bộ xử lý, bạn có thể có nhiều luồng tất cả chạy cùng một lúc ( đa luồng đồng thời hoặc SMT). Do đó, bạn phải rất cẩn thận trong việc truy cập dữ liệu đồng thời và bảo vệ dữ liệu của bạn bằng các biến thể, ngữ nghĩa, biến điều kiện, v.v. Nó thường rất khó để có được đúng.
Với một sợi, điều khiển chỉ chuyển đổi khi bạn nói với nó, thông thường với một lệnh gọi hàm có tên như thế yield()
. Điều này làm cho việc truy cập dữ liệu đồng thời dễ dàng hơn, vì bạn không phải lo lắng về tính nguyên tử của cấu trúc dữ liệu hoặc các đột biến. Miễn là bạn không chịu thua, sẽ không có nguy cơ bị cấm và có một sợi khác đang cố đọc hoặc sửa đổi dữ liệu bạn đang làm việc. Tuy nhiên, kết quả là, nếu sợi của bạn đi vào một vòng lặp vô hạn, thì không có sợi nào khác có thể chạy được, vì bạn không cho năng suất.
Bạn cũng có thể trộn các sợi và sợi, điều này dẫn đến các vấn đề mà cả hai phải đối mặt. Không được đề xuất, nhưng đôi khi nó có thể là điều đúng đắn nếu được thực hiện cẩn thận.
Trong Win32, một sợi là một loại luồng do người dùng quản lý. Một sợi có ngăn xếp riêng và con trỏ lệnh riêng của nó, v.v., nhưng các sợi không được HĐH lên lịch: bạn phải gọi SwitchToFiber một cách rõ ràng. Ngược lại, các luồng được lên lịch trước bởi hệ thống vận hành. Vì vậy, đại khái là một sợi là một luồng được quản lý ở cấp ứng dụng / thời gian chạy chứ không phải là một luồng hệ điều hành thực sự.
Hậu quả là các sợi rẻ hơn và ứng dụng có nhiều quyền kiểm soát hơn trong việc lên lịch. Điều này có thể quan trọng nếu ứng dụng tạo ra nhiều tác vụ đồng thời và / hoặc muốn tối ưu hóa chặt chẽ khi chúng chạy. Ví dụ: máy chủ cơ sở dữ liệu có thể chọn sử dụng các sợi thay vì các luồng.
(Có thể có các cách sử dụng khác cho cùng một thuật ngữ; như đã lưu ý, đây là định nghĩa Win32.)
Đầu tiên tôi khuyên bạn nên đọc phần giải thích này về sự khác biệt giữa các quy trình và chủ đề làm tài liệu nền.
Một khi bạn đã đọc rằng nó khá dễ dàng. Các luồng chủ đề được thực hiện hoặc trong kernel, trong không gian người dùng hoặc cả hai có thể được trộn lẫn. Sợi về cơ bản là các luồng được thực hiện trong không gian người dùng.
Trong phần 11.4 "Quy trình và chủ đề trong Windows Vista" trong Hệ điều hành hiện đại, Tanenbaum nhận xét:
Mặc dù các sợi được lên lịch hợp tác, nhưng nếu có nhiều luồng lập lịch cho các sợi, rất nhiều sự đồng bộ cẩn thận được yêu cầu để đảm bảo các sợi không can thiệp lẫn nhau. Để đơn giản hóa sự tương tác giữa các luồng và các sợi, thường chỉ hữu ích khi tạo ra nhiều luồng như có các bộ xử lý để chạy chúng và xác nhận các luồng cho mỗi luồng chỉ chạy trên một bộ xử lý có sẵn riêng biệt, hoặc thậm chí chỉ một bộ xử lý. Mỗi luồng sau đó có thể chạy một tập hợp con cụ thể của các sợi, thiết lập mối quan hệ một-nhiều giữa các luồng và các sợi giúp đơn giản hóa việc đồng bộ hóa. Mặc dù vậy vẫn còn nhiều khó khăn với sợi. Hầu hết các thư viện Win32 hoàn toàn không biết về các sợi và các ứng dụng cố gắng sử dụng các sợi như thể chúng là các luồng sẽ gặp phải các lỗi khác nhau. Hạt nhân không có kiến thức về các sợi và khi một sợi đi vào hạt nhân, luồng mà nó đang thực thi có thể chặn và hạt nhân sẽ lên lịch một luồng tùy ý trên bộ xử lý, khiến nó không có khả năng chạy các sợi khác. Vì những lý do này, các sợi hiếm khi được sử dụng trừ khi chuyển mã từ các hệ thống khác rõ ràng cần chức năng được cung cấp bởi các sợi.
Lưu ý rằng ngoài Chủ đề và Sợi, Windows 7 giới thiệu Lập lịch chế độ người dùng :
Lập lịch chế độ người dùng (UMS) là một cơ chế trọng lượng nhẹ mà các ứng dụng có thể sử dụng để lên lịch cho các luồng của riêng họ. Một ứng dụng có thể chuyển đổi giữa các luồng UMS trong chế độ người dùng mà không cần liên quan đến bộ lập lịch hệ thống và lấy lại quyền kiểm soát bộ xử lý nếu một luồng UMS chặn trong kernel. Các luồng UMS khác với các sợi trong đó mỗi luồng UMS có bối cảnh luồng riêng thay vì chia sẻ bối cảnh luồng của một luồng. Khả năng chuyển đổi giữa các luồng trong chế độ người dùng giúp UMS hiệu quả hơn nhóm luồng để quản lý số lượng lớn các mục công việc trong thời gian ngắn yêu cầu ít cuộc gọi hệ thống.
Thông tin thêm về chủ đề, sợi và UMS có sẵn bằng cách xem Dave Probert: Inside Windows 7 - Bộ lập lịch chế độ người dùng (UMS) .
Chủ đề được lên lịch bởi hệ điều hành (pre-emptive). Một luồng có thể bị dừng hoặc nối lại bất cứ lúc nào bởi HĐH, nhưng các sợi ít nhiều tự quản lý (hợp tác) và nhường cho nhau. Đó là, lập trình viên điều khiển khi các sợi thực hiện quá trình xử lý của chúng và khi quá trình xử lý đó chuyển sang một sợi khác.
Các luồng thường dựa vào nhân để làm gián đoạn luồng để nó hoặc luồng khác có thể chạy (được biết đến nhiều hơn là đa nhiệm Pre-emptive) trong khi các sợi sử dụng đa nhiệm hợp tác trong đó chính sợi đó từ bỏ thời gian chạy của nó. các sợi khác có thể chạy.
Một số liên kết hữu ích giải thích nó tốt hơn tôi có thể là:
Chủ đề ban đầu được tạo ra như các quá trình nhẹ. Theo cách tương tự, các sợi là một sợi nhẹ, dựa (đơn giản) vào chính các sợi để lên lịch cho nhau, bằng cách mang lại sự kiểm soát.
Tôi đoán bước tiếp theo sẽ là chuỗi mà bạn phải gửi tín hiệu cho họ mỗi khi bạn muốn họ thực hiện một lệnh (không giống như con trai 5yo của tôi :-). Ngày xưa (và thậm chí bây giờ trên một số nền tảng nhúng), tất cả các luồng đều là các sợi, không có chế độ trước và bạn phải viết các luồng của mình để hành xử độc đáo.
Định nghĩa sợi Win32 trên thực tế là định nghĩa "Chủ đề xanh" được thiết lập tại Sun microsystems. Không cần phải lãng phí sợi thuật ngữ trên luồng của một số loại, tức là, một luồng thực thi trong không gian người dùng dưới sự kiểm soát của mã người dùng / thư viện luồng.
Để làm rõ lập luận, hãy nhìn vào các ý kiến sau:
Chúng ta nên giả định rằng các quy trình được tạo thành từ các luồng và các luồng nên được làm từ các sợi. Với logic đó, sử dụng sợi cho các loại chủ đề khác là sai.