-----
4 Quản lý tiến trình
4.1
Thành phần cơ bản của một hệ thống máy tính
4.2 Chu trình đọc và thực thi lệnh
4.3 Khái
niệm về tiến trình
4.4 Khái niệm tiểu trình (thread)
4.5 Các
trạng thái của tiến trình
4.6 Các giải thuật/thuật toán điều phối tiến trình
4.7 Thực hành
[Program.cs]
using System;
using
System.Threading;
class Program
{
private int iterations;
private string message;
private int delay;
public Program(int iterations, string message, int delay)
{
this.iterations = iterations;
this.message = message;
this.delay = delay;
}
public void MyThread() // tạo tiểu trình
{
Thread thread = new Thread(DisplayMessage); // tạo tiểu trình
trỏ tới một hàm cụ thể
Console.WriteLine("{0}:Starting new
thread.",DateTime.Now.ToString("HH:mm:ss.ffff"));
thread.Start(); // chạy tiểu trình
}
public void DisplayMessage() // hàm sẽ được chạy
dưới hình thức một tiểu trình
{
for(int count =
0; count < iterations; count++)
{
Console.WriteLine("{0}:{1}", DateTime.Now.ToString("HH:mm:ss.ffff"), message);
Thread.Sleep(delay);
}
}
static void Main(string[] args)
{
Program example = new Program(500, "A thread example.", 500);
example.MyThread(); // gọi và thực thi tiểu
trình từ chương trình chính (main)
for(int count =
0; count < 1000; count++)
{
Console.WriteLine("{0} : Continue
processing...",
DateTime.Now.ToString("HH:mm:ss.ffff"));
Thread.Sleep(500);
}
Console.WriteLine("Main method complete. Press
Enter.");
}
}
Giải thích để hiểu đoạn
mã ở trên
Trước khi giải thích các đoạn mã ở trên, cần tìm hiểu ngắn gọn
một số khái niệm liên quan.
Phần mềm máy tính là tập hợp các lệnh và dữ liệu,
được dùng để hướng dẫn máy tính thực hiện các chức năng cụ thể.
Tập hợp các lệnh được gọi là chương trình.
Một chương trình có thể ở trạng thái tĩnh là các lệnh đang
được lưu trong các tập tin trên đĩa cứng.
Một chương trình có thể ở trạng thái động là các lệnh đang
được thực thi trong RAM và CPU.
Tiến trình là một chương trình ở trạng
thái động, mỗi tiến trình có một không gian địa chỉ (trong RAM), một con trỏ lệnh,
một tập các thanh ghi (trong CPU) và stack riêng. Tiến trình có thể cần đến một
số tài nguyên như CPU, bộ nhớ chính, các tập tin và thiết bị nhập/xuất.
Quá trình chạy của một tiến trình:
Chạy
chương trình Program.cs và xem tiến trình trong Task Manager (thiết lập vòng lặp
trong hàm Main khoảng 1000 lần để dễ quan sát):
Tiểu trình là gì?
Một tiến trình có thể tạo nhiều tiểu trình, mỗi tiểu trình
thực hiện một chức năng cụ thể.
Các tiểu trình trong cùng một tiến trình dùng chung không
gian địa chỉ của tiến trình nhưng có con trỏ lệnh, tập các thanh ghi và stack
riêng.
Tiểu trình cũng là đơn vị xử lý cơ bản trong hệ thống, nó
cũng xử lý tuần tự đoạn mã của nó, các tiểu trình cũng chia sẻ thời gian xử lý
của CPU như các tiến trình.
Các tiểu trình trong một tiến trình chia sẻ một không gian địa
chỉ chung, điều này có nghĩa các tiểu trình có thể chia sẻ các biến toàn cục của
tiến trình, có thể truy xuất đến stack của tiểu trình khác trong cùng tiến
trình. Như vậy với mô hình tiểu trình, trong hệ thống có thể tồn tại nhiều dòng
xử lý cùng chia sẻ một không gian địa chỉ bộ nhớ, các dòng xử lý này hoạt động
song song với nhau.
Giải thích đoạn mã trong Program.cs:
Chương trình Program.cs gồm hai tiểu trình: tiểu
trình chính (Main) và tiểu trình example.
Để tạo thread trong C#:
Bước 1: Tạo một hàm cần thực thi riêng biệt, song song với
tiểu trình chính (hàm Main). Ví dụ:
public void DisplayMessage() // hàm sẽ được chạy
dưới hình thức một tiểu trình
{
for(int count =
0; count < iterations; count++)
{
Console.WriteLine("{0}:{1}", DateTime.Now.ToString("HH:mm:ss.ffff"), message);
Thread.Sleep(delay);
}
}
Bước 2: Tạo tiểu trình bằng cách tạo ra một đối tượng thuộc
lớp Thread, truyền vào phương thức khởi tạo tên hàm đã được tạo ở bước 1; gọi
phương thức Start() để chạy tiểu trình. Ví dụ:
public void MyThread() // tạo tiểu trình
{
Thread thread = new Thread(DisplayMessage); // tạo tiểu trình
trỏ tới một hàm cụ thể
Console.WriteLine("{0}:Starting new
thread.",DateTime.Now.ToString("HH:mm:ss.ffff"));
thread.Start(); // chạy tiểu trình
}
Bước 3: Chạy tiểu trình chính (hàm Main), trong tiểu trình
chính sẽ gọi tiểu trình được tạo ra ở Bước 2. Ví dụ:
static void Main(string[] args)
{
Program example = new Program(500, "A thread example.", 500);
example.MyThread(); // gọi và thực thi tiểu
trình từ chương trình chính (main)
for(int count =
0; count < 1000; count++)
{
Console.WriteLine("{0} : Continue
processing...",
DateTime.Now.ToString("HH:mm:ss.ffff"));
Thread.Sleep(500);
}
Console.WriteLine("Main method complete. Press
Enter.");
}
Quan sát kết quả sẽ thấy các câu thông báo của hàm Main() và hàm DisplayMessage() được hiển thị đan xen nhau (do chạy song song). Trong các tiểu trình có dùng lệnh Sleep() để dừng chương trình một thời gian, giúp quan sát kết quả dễ hơn.
4.7.2 Tiểu trình dùng chung vùng nhớ
Như đã đề cập trong phần khái niệm tiểu trình: các tiểu
trình trong cùng một tiến trình sẽ dùng chung không gian địa chỉ của tiến trình
(trong RAM) nhưng có con trỏ lệnh, tập các thanh ghi và stack riêng.
Phần này sẽ viết một chương trình gồm tiểu trình chính (hàm Main)
và hai tiểu trình con. Hai tiểu trình con sẽ tham chiếu tới cùng một biến (một
vùng nhớ trên RAM). Biến dùng chung giữa hai tiểu trình con có tên là count;
hai tiểu trình con có tên là TieuTrinhCong và TieuTrinhTru.
Ý tưởng của chương trình:
– Gán cho biến count giá trị ban đầu (ví dụ: count = 10)
– Tiểu trình chính (hàm Main) sẽ gọi hai tiểu trình con
– TieuTrinhCong(): sẽ tăng liên tục biến count lên 2500 lần
– TieuTrinhTru(): sẽ giảm liên tục biến count lên 2500 lần
– Sau khi chạy xong hai tiểu trình con, sẽ xuất giá trị của
biến count trong tiểu trình chính để quan sát kết quả của biến count.
[Thread_Cong_Tru.cs]
using System;
using
System.Threading;
class Thread_Cong_Tru
{
private int count = 10;
public void HamCong()
{
for(int i = 0; i
< 2500; i++)
{
count = count + 1;
Console.WriteLine("Gia tri count trong ham
cong: " + count);
Thread.Sleep(300);
}
}
public void HamTru()
{
for (int i = 0; i
< 2500; i++)
{
count = count - 1;
Console.WriteLine("Gia tri count trong ham tru:
" + count);
Thread.Sleep(300);
}
}
static void Main(string[] args)
{
Thread_Cong_Tru test = new Thread_Cong_Tru();
Console.WriteLine("Gia tri khoi tao cua bien
count (trong tieu trinh Main): " + test.count);
// tạo và chạy
tiểu trình cộng
Thread TieuTrinhCong = new Thread(test.HamCong);
TieuTrinhCong.Start();
// tạo và chạy
tiểu trình trừ
Thread TieuTrinhTru = new Thread(test.HamTru);
TieuTrinhTru.Start();
Console.WriteLine("Gia tri ket thuc cua bien
count (trong tieu trinh Main): " + test.count);
}
}
// Giá trị của biến count có thể là 9, 10, 11, 12, 13: do biến
dùng chung này bị thao tác cùng lúc từ hai tiểu trình nên không thể kiếm soát được
giá trị. Đây là lý do cần phải đồng bộ hóa giữa các tiến/tiểu trình.
---------------------------------------
Lab 8. Viết chương trình cho phép nhập một số nguyên dương, tìm các số nguyên tố và số chính phương từ 0 tới số vừa nhập. Sử dụng phương pháp lập trình tuần tự, nghĩa là cho người dùng nhập vào một số, chương trình sẽ chạy chức năng tìm và xuất số nguyên dương ra màn hình trước, sau đó sẽ chạy chức năng tìm và xuất số chính phương ra màn hình. (sử dụng ngôn ngữ lập trình tùy chọn)
4.8 Câu hỏi
ôn tập
Cập nhật: [1/6/2021]
-------
Bài tiếp theo: Hệ điều hành (4) - Liên lạc và đồng bộ hóa giữa các tiến trình
Danh sách các bài học