Trình quản lý tác vụ đang nói hệ thống đang chạy với hơn một nghìn luồng


17

Tôi mở Trình quản lý tác vụ và nhìn vào khu vực "Hệ thống" và thấy:

Chủ đề: 1337

Vì tôi có bộ xử lý lõi kép có siêu phân luồng khả dụng (nghĩa là bốn luồng), làm sao có thể có hơn 1000 luồng khi bộ xử lý của tôi chỉ có bốn luồng ?


3
Không phải đó là lý do tại sao họ gọi nó là siêu đọc ? :)
một CVn

9
Gee, cuối cùng họ đã phát minh ra "đa chương trình" ??? (Đây là năm 1967, phải không?)
Daniel R Hicks

10
Có ai đó chỉ cần thay đổi số là 1337?
Erty Seidohl

11
Làm thế nào một công ty có bốn bàn có 1337 nhân viên? Dễ dàng; các nhân viên thay phiên nhau sử dụng bàn làm việc.
Eric Lippert

Câu trả lời:


50

Câu trả lời đơn giản là không phải tất cả các luồng đều được thực thi đồng thời. Để giải thích đầy đủ hơn, hãy đọc tiếp.

Lập lịch tác vụ của hệ điều hành thường được nghĩ đến để lên lịch cho các ứng dụng và làm như vậy cho phép bạn thực hiện một tác vụ trong khi máy tính đang làm việc khác. Vào thời xưa, bài kiểm tra đa nhiệm về đa nhiệm là định dạng một đĩa mềm trong khi làm việc khác. Nếu bạn muốn thực sự đưa HĐH vào thử nghiệm, bạn sẽ định dạng đĩa mềm trong khi tải xuống tệp qua modem được kết nối với cổng nối tiếp. Khi phần cứng trở nên đủ mạnh để thực sự làm điều đó một cách có ý nghĩa, phát lại video đôi khi cũng xuất hiện trong các thử nghiệm như vậy. Nếu bộ lập lịch tác vụ của HĐH có thể xử lý các tác vụ đó một cách trơn tru, thì nó có thể xử lý mọi thứ.

Tuy nhiên, trình lập lịch tác vụ không thực sự lên lịch cho các ứng dụng (quy trình), nó lập lịch các luồng . Mỗi ứng dụng có ít nhất một luồng, nhưng có khả năng có thể sử dụng một số lượng lớn các luồng để phân chia công việc mà nó thực hiện thành các phần liên quan hoặc độc lập. Ví dụ, thông thường, một ứng dụng có một luồng xử lý giao diện người dùng và tạo một luồng khác khi người dùng bắt đầu một hoạt động có khả năng chạy dài (có thể là những việc như in, tính toán lại bảng tính, môi trường phát triển đang làm tra cứu biểu tượng, v.v.) Một số môi trường lập trình giới thiệu một số lượng chủ đề vô hình cho lập trình viên; ví dụ, Java.NET có thể thực hiện thu gom ráctrong một luồng riêng biệt, nằm ngoài tầm kiểm soát ngay lập tức của lập trình viên. Một số chương trình tạo ra một số chủ đề sớm và tập hợp chúng, bởi vì tạo chủ đề mới là một hoạt động tương đối tốn kém (vì vậy bạn không nhất thiết phải tạo một chủ đề mỗi khi bạn cần một chủ đề). Bất cứ điều gì thực hiện xem trước thường được thực hiện trong một luồng riêng biệt, vì vậy phần còn lại của giao diện người dùng vẫn phản hồi trong khi bản xem trước đang được tạo. Và như thế. Được kết hợp với nhau, tất cả điều này có nghĩa là số lượng luồng trên hệ thống bất cứ lúc nào có thể dễ dàng gấp nhiều lần số lượng quy trình.

Mỗi luồng có thể ở một trong một vài trạng thái có thể, nhưng sự khác biệt quan trọng nhất là giữa trạng thái chạy , chạychờ ; thuật ngữ có thể khác nhau một chút, nhưng đó là ý tưởng chung. Tại bất kỳ thời điểm nào, chỉ có một luồng trên mỗi luồng ảo (vì siêu phân luồng và các công nghệ tương tự) lõi CPU có thể chạy (nghĩa là thực thi các hướng dẫn mã máy), nhưng bất kỳ số lượng luồng nào cũng có thể chạy được (có nghĩa là nó phải là ứng cử viên CPU trong lần tiếp theo bộ lập lịch cần đưa ra quyết định về luồng nào sẽ được phép chạy). Đang chờ đợi Các chủ đề (còn được gọi là bị chặn) chỉ là như vậy, chờ đợi một cái gì đó - trường hợp phổ biến nhất có lẽ là nó đang chờ người dùng, đĩa hoặc mạng I / O (đặc biệt là đầu vào của người dùng rất chậm).

Số lượng luồng bạn thấy trong trình quản lý tác vụ là tổng số luồng trong bất kỳ trạng thái nào. Ví dụ, hệ thống Windows 7 tôi đang gõ này hiện có khoảng 70 quy trình được bắt đầu nhưng gần 900 luồng. Với tất cả các quy trình nền để xử lý các tác vụ khác nhau và cách chúng có thể được chia thành vô số các chủ đề, đây không phải là một con số quá đáng.

Đi sâu hơn một chút vào chiều sâu của việc triển khai kỹ thuật, cốt lõi của bộ lập lịch tác vụ của hệ điều hành đa nhiệm ưu tiên thường là một loại móc nối phần cứng. Điều này có nghĩa rằng các hạt nhân có thể ngăn chặn sự CPU khi nó không có công việc hữu ích để thực hiện (điều này là gần như chắc chắn là một trong những lý do này, nếu không muốn nói lý do, tại sao kiểm tra Linux các HLThướng dẫn khi khởi động trên IA-32CPU tương thích và có thể kiểm tra tương tự trên các kiến ​​trúc khác), an toàn với kiến ​​thức rằng tại một thời điểm nào đó xác định hợp lý thời gian trong tương lai, một ngắt sẽ kích hoạt và bộ lập lịch nhiệm vụ sẽ được gọi. Do ngắt hoạt động bất kể CPU đang thực hiện công việc nào khác (đó là ý tưởng đằng sau các ngắt), bộ lập lịch được thực thi thường xuyên và có cơ hội xác định luồng nào sẽ được thực hiện trong lát cắt thời gian sau. Vì các chuyển đổi ngữ cảnh tương đối đắt tiền, nên thường có thể (ít nhất là thông qua mã nguồn) để điều chỉnh mức độ mạnh mẽ của trình lập lịch chuyển đổi giữa các luồng; chuyển đổi chủ đề thường xuyên hơn làm cho hệ thống trở nên nhạy hơn, nhưng chi phí chuyển đổi có nghĩa là thời gian tổng thể để hoàn thành một tập hợp các nhiệm vụ nhất định là lâu hơn. các nhanh nhấthệ thống sẽ là một hệ thống chỉ chuyển đổi giữa các luồng khi luồng chạy không thể chạy được nữa (nghĩa là nó bị chặn chờ đợi trên một cái gì đó hoặc nó đã hoàn thành công việc của nó) bởi vì điều đó giảm thiểu chi phí, trong khi hệ thống nhạy nhất sẽ chuyển đổi giữa các luồng mỗi khi bộ lập lịch được gọi vì điều đó giảm thiểu thời gian trung bình để chờ trước khi một luồng cụ thể có thời gian CPU. Cài đặt lý tưởng thường nằm ở đâu đó ở giữa hai điều này và sự đánh đổi giữa các lựa chọn đó có thể là một lý do lớn khiến Linux cung cấp nhiều bộ lập lịch để lựa chọn cũng như một số tham số điều chỉnh thông qua cấu hình kernel.

Mặt khác, các hệ điều hành và môi trường đa nhiệm hợp tác ( Windows 3.x là một ví dụ), dựa vào từng ứng dụng để thường xuyên nhường quyền kiểm soát cho bộ lập lịch. Thường có một hàm API đặc biệt có nghĩa là để làm điều đó và thông thường, nhiều hàm API sẽ thực hiện nó như một phần của luồng thực thi nội bộ của chúng, bởi vì nó giúp trải nghiệm người dùng mượt mà hơn. Cách tiếp cận thiết kế đó hoạt động tốt miễn là tất cả các ứng dụng đều hoạt động tốt và kiểm soát các khoảng thời gian ngắn trong bất kỳ hoạt động dài nào (chạy dài có nghĩa là nhiều hơn một phần nhỏ của giây), nhưng một ứng dụng không thể làm tắc nghẽn toàn bộ hệ thống. Đây là một lý do lớn khiến Windows 3.x làm rất kém trong bài kiểm tra đa nhiệm mà tôi đã đề cập ở trên, trong khi OS / 2đi bộ vui vẻ trong khi thực hiện các nhiệm vụ tương tự trên cùng một phần cứng: một ứng dụng có thể yêu cầu ổ đĩa mềm ghi một khu vực nhất định và thời gian cần thực hiện trước khi cuộc gọi trở lại thực sự có thể đo lường được (hàng chục đến hàng trăm mili giây hoặc hơn); một hệ thống đa nhiệm được ưu tiên sẽ ngắt lịch trình trong lệnh gọi theo lịch trình tiếp theo của nó, lưu ý rằng luồng hiện đang "chạy" thực sự bị chặn bởi lệnh gọi và chỉ cần chuyển sang một luồng khác có thể chạy được. (Trong thực tế, nó liên quan nhiều hơn một chút, nhưng đó là ý tưởng chung.)

Trong cả hai môi trường đa nhiệm và hợp tác ưu tiên, cũng có khả năng các luồng khác nhau có các ưu tiên khác nhau. Ví dụ, điều quan trọng hơn là phải thực hiện kịp thời luồng xử lý nhận dữ liệu qua liên kết truyền thông so với luồng cập nhật hiển thị thời gian hệ thống, vì vậy luồng nhận có mức độ ưu tiên cao và luồng cập nhật hiển thị thời gian có mức độ ưu tiên thấp . Các ưu tiên của luồng đóng vai trò trong quyết định của trình lập lịch biểu cho phép thực hiện luồng nào (ví dụ: rất đơn giản, các luồng ưu tiên cao phải luôn luôn thực thi trước các luồng có mức độ ưu tiên thấp, vì vậy ngay cả khi luồng có mức độ ưu tiên thấp còn phải làm, nếu luồng có mức độ ưu tiên cao có thể chạy được thì nó vẫn được ưu tiên), nhưng các quyết định lập lịch cụ thể như vậy không ảnh hưởng đến thiết kế cơ chế bên dưới.


11
Tôi yêu "đặc biệt là đầu vào của người dùng rất chậm"
John Dvorak

"Các luồng" mà CPU "có" chỉ số lượng mà nó có thể thực thi đồng thời tại bất kỳ thời điểm nào. Nó chuyển đổi giữa các luồng hoạt động, cho mỗi lượt hoặc chia sẻ CPU trong một lát thời gian, khi có thể. Các quy trình / luồng "bị chặn" hoặc chờ trên I / O (chẳng hạn như đầu vào đĩa, bàn phím / chuột, v.v.) hoặc một cái gì đó khác (chẳng hạn như các nguyên thủy đồng bộ hóa như mutexes, v.v.) bỏ qua lượt của chúng.
LawrenceC

1
Nhận xét rất hay để yêu cầu làm rõ, nhưng chúng không phù hợp để thảo luận mở rộng và đôi khi trở nên khó đọc. Bạn có thể vui lòng mang nó đến Super User Chat thay thế? Cảm ơn bạn.
slhck

1
@slhck Tôi đã tạo một phòng, nhưng không thể tìm thấy bất kỳ cách nào để di chuyển cuộc thảo luận trong những bình luận này, điều này sẽ rất tuyệt. Đó có phải là thứ bạn có thể làm thủ công như một người điều hành không? chat.stackexchange.com/rooms/9547/ Mạnh
một CVn

1
Tiếc là không có. Có một quy trình di chuyển tự động không thể được kích hoạt bằng tay, nhưng chúng tôi không thể di chuyển nhận xét đến phòng trò chuyện. Chúng tôi sẽ để các bình luận ở đây trong thời gian này, nhưng tôi khuyến khích những người khác theo dõi cuộc thảo luận trong phòng trò chuyện mà bạn đã tạo.
slhck

18

Hãy nghĩ về một đường cao tốc bốn làn với 1037 xe.

Hệ điều hành của bạn cần rất nhiều quy trình đang chạy để hoạt động cho nhiều dịch vụ. Ngay cả các chương trình đồ họa đơn giản nhất cũng sẽ yêu cầu lập trình đa luồng. Khi bạn nghĩ về rất nhiều chương trình đã mở, bạn thấy cần phải chia sẻ tài nguyên sức mạnh tính toán.

Những gì trình quản lý tác vụ của bạn đang hiển thị là tải hệ thống hiện tại. Thông số kỹ thuật comp của bạn đang hiển thị là có bao nhiêu luồng (ở lối vào) được chấp nhận để thực hiện song song. Không cần nhập nhiều vào sự khác biệt giữa các tính năng siêu phân luồng và đa lõi, với việc chấp nhận luồng frontend logic hơn, một hệ thống thường sẽ hoạt động tốt hơn.


8
"Ngay cả các chương trình đồ họa đơn giản nhất cũng sẽ yêu cầu lập trình đa luồng." Sai lầm. Hoàn toàn có thể viết các ứng dụng GUI đơn luồng; cho đến Windows 95, cho tất cả ý định và mục đích mọi người đã làm theo cách đó. Nó làm cho một số tác vụ phức tạp hơn (ví dụ, in nền là tầm thường với nhiều luồng nhưng quyết định không tầm thường trong một ứng dụng luồng đơn, đặc biệt nếu bạn cũng bị hạn chế bộ nhớ như trường hợp sau đó), nhưng có một sự khác biệt rất lớn giữa " X được làm cho dễ dàng hơn bởi Y "và" X yêu cầu Y ".
một CVn

8
@ MichaelKjorling: "cho đến Windows 95, cho tất cả ý định và mục đích mọi người đã làm theo cách đó" * - thực sự? Ngay cả trên các hệ thống * nix chạy Motif trong thập niên 80?
LarsH

@LarsH Điểm hay, và một điều tôi nghĩ là quá muộn để chỉnh sửa thành bình luận. Nhưng điều đó không phủ nhận điểm: cụ thể là, hoàn toàn có thể viết các ứng dụng GUI đơn luồng. Bạn không cần đa luồng cho điều đó, mặc dù nó làm cho một số nhiệm vụ (đáng kể) dễ dàng hơn đối với người lập trình.
một CVn

@ MichaelKjorling: Tôi đồng ý, nó không phủ nhận quan điểm của bạn, đó là một điểm hợp lệ. (Tôi cũng không nghĩ tuyên bố không chính xác của uprego phủ nhận quan điểm của anh ấy.)
LarsH

Như một ví dụ cho những gì @ MichaelKjorling đã nói, Visual Basic (trước .NET) là ngôn ngữ lập trình không có hỗ trợ đa luồng. Tất cả mọi thứ đã được chạy trên một chủ đề duy nhất. Nếu bạn muốn xử lý đầu vào của người dùng ở giữa một hoạt động dài, bạn sẽ gọi DoEvents, sẽ xử lý hàng đợi tin nhắn - nhưng điều đó được thực hiện trên cùng một luồng và sẽ chặn hoạt động chạy dài đó cho đến khi tất cả các tin nhắn được xử lý . (Tất nhiên, bạn có thể gọi các hàm API Win32 và / hoặc tạo các quy trình bổ sung, nhưng tại thời điểm đó, bạn cũng có thể sử dụng một trong các ngôn ngữ cấp thấp hơn.)
Bob

5

Chúng ta nên lùi lại và tự hỏi: Làm thế nào một máy tính với một CPU có hai luồng?

Chủ đề là các thực thể phần mềm, không phải phần cứng. Để có một luồng khác, bạn chỉ cần bộ nhớ cho các đối tượng tạo nên luồng, chẳng hạn như cấu trúc mô tả và ngăn xếp.

Hệ điều hành chuyển đổi giữa các luồng tại nhiều thời điểm khác nhau, như bên trong các ngắt nhất định (chẳng hạn như ngắt hẹn giờ) hoặc khi các luồng thực hiện cuộc gọi vào hệ điều hành.

Trong số tất cả các luồng tồn tại trong hệ thống, chỉ có một tập hợp con thường ở trạng thái thường được gọi là "runnable". Các chuỗi có thể chạy được háo hức để chạy: chúng đang thực thi hoặc đang ngồi trong "hàng đợi chạy", chờ đợi để được gửi bởi bộ lập lịch. Các chủ đề không thể chạy được là "bị chặn", đang chờ để lấy một số tài nguyên hoặc nhận đầu vào hoặc "ngủ" giống như bị chặn trên đầu vào, trong đó "đầu vào" là thời gian trôi qua. "Chuyển đổi ngữ cảnh" diễn ra khi chức năng lập lịch biểu trong hệ điều hành xem xét hàng đợi chạy của bộ xử lý và chọn một luồng khác để thực thi.

Đừng nhầm lẫn với "siêu phân luồng" , đó là tên của Intel cho một tính năng phần cứng cụ thể.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.