148
Chương 4: Tiểu trình, tiến trình, và sự đồng bộ
Lớp
ManualResetEvent
phải được chuyển đổi qua lại giữa signaled và unsignaled bằng
phương thức
Set
và
Reset
của nó. Gọi
Set
trên một
ManualResetEvent
sẽ đặt trạng thái của nó
là signaled, giải phóng tất cả các tiểu trình đang đợi sự kiện. Chỉ khi gọi
Reset
mới làm cho
ManualResetEvent
trở thành unsignaled.
Một
Mutex
là signaled khi nó không thuộc sở hữu của bất kỳ tiểu trình nào. Một tiểu trình
giành quyền sở hữu
Mutex
lúc khởi dựng hoặc sử dụng một trong các phương thức được liệt
kê trong bảng 4.2. Quyền sở hữu
Mutex
được giải phóng bằng cách gọi phương thức
Mutex.ReleaseMutex
(ra hiệu
Mutex
và cho phép một tiểu trình khác thu lấy quyền sở hữu
này). Thuận lợi chính của
Mutex
là bạn có thể sử dụng chúng để đồng bộ hóa các tiểu trình qua
các biên tiến trình. Mục 4.12 đã trình bày cách sử dụng
Mutex
.
Ngoài các chức năng vừa được mô tả, điểm khác biệt chính giữa các lớp
WaitHandle
và lớp
Monitor
là lớp
Monitor
được hiện thực hoàn toàn bằng mã lệnh được-quản-lý, trong khi các
lớp
WaitHandle
cung cấp vỏ bọc cho các chức năng bên dưới của của hệ điều hành. Điều này
dẫn đến hệ quả là:
•
Sử dụng lớp
Monitor
đồng nghĩa với việc mã lệnh của bạn sẽ khả chuyển hơn vì không
bị lệ thuộc vào khả năng của hệ điều hành bên dưới.
•
Bạn có thể sử dụng các lớp dẫn xuất từ
WaitHandle
để đồng bộ hóa việc thực thi của các
tiểu trình được-quản-lý và không-được-quản-lý, trong khi lớp
Monitor
chỉ có thể đồng
bộ hóa các tiểu trình được-quản-lý.
9.
9.
T o m t đ i t
ng t p h p có tính ch t an-toàn-v -ti u-trình
ạ ộ ố ượ
ậ ợ
ấ
ề ể
T o m t đ i t
ng t p h p có tính ch t an-toàn-v -ti u-trình
ạ ộ ố ượ
ậ ợ
ấ
ề ể
Bạn muốn nhiều tiểu trình có thể đồng thời truy xuất nội dung của một tập hợp
một cách an toàn.
Sử dụng lệnh
lock
để đồng bộ hóa các tiểu trình truy xuất đến tập hợp, hoặc truy
xuất tập hợp thông qua một vỏ bọc có tính chất an-toàn-về-tiểu-trình (thread-
safe).
Theo mặc định, các lớp tập hợp chuẩn thuộc không gian tên
System.Collections
và
System.Collections.Specialized
sẽ hỗ trợ việc nhiều tiểu trình đồng thời đọc nội dung của
tập hợp. Tuy nhiên, nếu một hay nhiều tiểu trình này sửa đổi tập hợp, nhất định bạn sẽ gặp rắc
rối. Đó là vì hệ điều hành có thể làm đứt quãng các hành động của tiểu trình trong khi tập hợp
chỉ mới được sửa đổi một phần. Điều này sẽ đưa tập hợp vào một trạng thái vô định, chắc
chắn khiến cho một tiểu trình khác truy xuất tập hợp thất bại, trả về dữ liệu sai, hoặc làm hỏng
tập hợp.
Sử dụng “đồng bộ hóa tiểu trình” sẽ sinh ra một chi phí hiệu năng. Cứ để tập
hợp là không-an-toàn-về-tiểu-trình (non-thread-safe) như mặc định sẽ cho hiệu
năng tốt hơn đối với các trường hợp có nhiều tiểu trình không được dùng đến.
Tất cả các tập hợp thông dụng nhất đều hiện thực một phương thức tĩnh có tên là
Synchronized
; bao gồm các lớp:
ArrayList
,
Hashtable
,
Queue
,
SortedList
, và
Stack
(thuộc
không gian tên
System.Collections
). Phương thức
Synchronized
nhận một đối tượng tập hợp