Đa nhiệm hợp tác và Đa nhiệm ưu tiên

Xu hướng lập trình hiện nay là viết chương trình đa nhiệm (multitasking) để tận dụng tối đa CPU đa lõi. Có 2 cấp độ đa nhiệm: cấp độ hệ điều hànhcấp độ chương trình. Có 2 kiểu đa nhiệm: đa nhiệm hợp tác (cooperative) và đa nhiệm ưu tiên (preemptive). Mục đích bài viết này là giải thích 4 (2×2) khái niệm trên.

Có 2 loại máy ảo: máy ảo cho hệ điều hành (như VMWare) và máy ảo cho chương trình (như máy ảo Java). Từ “máy ảo” trong bài viết này dùng để chỉ loại thứ 2.

Cấp độ đa nhiệm

Các hệ điều hành hiện đại như Windows và Linux đều là những hệ điều hành đa nhiệm. Đa nhiệm ở cấp độ hệ điều hành thể hiện ở chỗ cùng lúc hệ điều hành có thể chạy nhiều chương trình (process), ví dụ có thể cùng lúc vừa bật trình duyệt vừa bật chương trình soạn thảo văn bản. Bản thân một chương trình cũng có thể chia nhỏ thành nhiều luồng (thread), ví dụ một trình duyệt có thể vừa đọc dữ liệu từ Internet vừa xử lý sự kiện con chuột hay bàn phím. Các hệ điều hành hiện đại đều hỗ trợ sẵn việc tạo luồng, luồng tạo bởi sự hỗ trợ của hệ điều hành gọi là native thread. Một loại luồng khác gọi là green thread, là luồng tạo ra bởi máy ảo. Tùy loại máy ảo mà luồng tạo ra trong chương trình có thể là native (như đối với Java 1.2 trở lên) hay green (như đối với Erlang, Java 1.1 trở xuống, và Ruby 1.8 trở xuống). Chương trình viết bằng C/C++ không chạy trên máy ảo, do đó luồng của chúng chắc chắn là native.

Vì đa số lập trình viên đều viết chương trình chứ không viết hệ điều hành và đa số ngôn ngữ hiện đại đều chạy trên máy ảo chứ không chạy trực tiếp trên hệ điều hành, nên đa số lập trình viên chỉ cần quan tâm đến đa nhiệm ở cấp độ máy ảo là đủ.

Cấp độ đa nhiệm cũng dễ giải thích phải không? Tiếp theo chúng ta giải thích kiểu đa nhiệm, hơi khó hiểu một chút.

Kiểu đa nhiệm

Đa nhiệm hợp tác nguyên thủy hơn đa nhiệm ưu tiên. Ở cấp độ hệ điều hành, hiện hầu như tất cả các hệ điều hành hiện đại đều dùng đa nhiệm ưu tiên, ví dụ Windows 3.1 dùng kiểu đầu, còn Windows 95 trở lên dùng kiểu sau. Vì các hệ điều hành hiện đại đều dùng đa nhiệm ưu tiên, nên chúng ta chỉ giải thích kiểu đa nhiệm ở cấp độ máy ảo/thư viện.

Đa nhiệm hợp tácđa nhiệm ưu tiên là 2 thuật ngữ hơi khó hiểu vì bản thân 2 cụm từ này có vẻ không chính xác lắm. Chính xác và dễ hiểu hơn có lẽ phải gọi là đa nhiệm độc tàiđa nhiệm cưỡng bức. Giả sử có N job được chia cho M thread trong thread pool:

  • Thường N > M. Hệ thống thường chạy tối ưu khi M xấp xỉ số lượng và xấp xỉ bội số của số lượng lõi CPU, vì lúc này mỗi lõi đảm nhiệm số lượng thread xấp xỉ nhau.
  • Một job muốn chạy thì phải chiếm hữu (được phân phát) một thread nào đó. Job có thể coi là hàng hóa và thread có thể coi là xe vận chuyển, hàng hóa muốn di chuyển từ A đến B thì phải cưỡi trên một xe nào đó.
  • Đa nhiệm hợp tác: khi một job chạy trên một thread thì nó sẽ chạy đến khi nào nó kết thúc, khi nó chưa kết thúc thì các job khác không được sử dụng thread nó đang chiếm để chạy.
  • Đa nhiệm ưu tiên: khi job đang chạy nửa đường, thì hệ thống có thể cưỡng bức bắt nó tạm thời xuống xe, để giao xe cho job khác, một lúc sau job lúc nãy bị dừng xe giữa đường sẽ được giao xe (không nhất thiết phải là xe ban đầu) để chạy tiếp, rất có thể chạy được một lúc lại bị cưỡng bức tiếp :D.
  • Với đa nhiệm hợp tác thì nếu job nào đó chạy chưa xong, chưa giao lại xe, thì các job khác chịu chết. Đa nhiệm ưu tiên công bằng hơn, các job được đảm bảo luôn có xe để chạy, mặc dù có thể bị cưỡng bức tạm thời ngừng lại giữa đường. Đa nhiệm ưu tiên chạy êm hơn (soft realtime), Erlang dùng đa nhiệm ưu tiên còn Clojure dùng đa nhiệm hợp tác.

Nguồn: Công Nghệ Thông Tin (cntt.tv)

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s