Giải pháp cho Vấn đề Critical Section - ndtien-practice-c
Download
Report
Transcript Giải pháp cho Vấn đề Critical Section - ndtien-practice-c
Chương 6: Đồng bộ hóa tiến
trình
Nguyên lý hệ điều hành
Nguyễn Đức Thịnh - ĐHNNHN
Nội dung
Kiến thức nền
Vấn đề về Critical Section
Lời giải của Peterson
Phần cứng đồng bộ hóa
Semaphore
Các vấn đề cổ điển của đồng bộ hóa
Monitor
Các ví dụ
Giao tác nguyên tố (Atomic Transactions)
Nguyên lý hệ điều hành
6.2
Nguyễn Đức Thịnh - ĐHNNHN
Mục tiêu
Vấn đề critical-section, các giải pháp được dùng để đảm bảo tính nhất
quán của dữ liệu chia sẻ
Trình bày giải pháp phần cứng và phần mềm của critical section
problem
Giới thiệu khái niệm về atomic transaction và trình bày cơ chế để đảm
bảo tính nguyên tố (atomicity)
Nguyên lý hệ điều hành
6.3
Nguyễn Đức Thịnh - ĐHNNHN
Kiến thức nền
Truy cập đồng thời tới dữ liệu chia sẻ có thể gây ra sự không nhất
quán
Duy trì sự nhất quán dữ liệu cho ta cơ chế để đảm bảo sự thực thi có
trật tự của các tiến trình tương tác
Giả sử rằng chúng ta muốn cung cấp một giải pháp cho vấn đề
consumer-producer làm đầy các bộ đệm (buffer). Ta có thể làm vậy
bằng cách dùng một bộ đếm (counter) theo dõi số lượng các item
trong buffer. Ban đầu, count được đặt bằng 0. Nó được tăng lên bởi
producer sau khi nó tạo ra một item mới và được giảm đi bởi
consumer sau khi nó tiêu thụ một item.
Nguyên lý hệ điều hành
6.4
Nguyễn Đức Thịnh - ĐHNNHN
Producer
while (true) {
/* produce an item and put in nextProduced */
while (count == BUFFER_SIZE)
; // do nothing
buffer [in] = nextProduced;
in = (in + 1) % BUFFER_SIZE;
count++;
}
Nguyên lý hệ điều hành
6.5
Nguyễn Đức Thịnh - ĐHNNHN
Consumer
while (true) {
while (count == 0)
; // do nothing
nextConsumed = buffer[out];
out = (out + 1) % BUFFER_SIZE;
count--;
/* consume the item in nextConsumed */
}
Nguyên lý hệ điều hành
6.6
Nguyễn Đức Thịnh - ĐHNNHN
Race Condition
count++ có thể được cài đặt như sau
register1 = count
register1 = register1 + 1
count = register1
count– có thể được cài đặt như sau
register2 = count
register2 = register2 - 1
count = register2
Giả sử rằng ban đầu “count = 5”:
S0: producer thực thi register1 = count {register1 = 5}
S1: producer thực thi register1 = register1 + 1 {register1 = 6}
S2: consumer thực thi register2 = count {register2 = 5}
S3: consumer thực thi register2 = register2 - 1 {register2 = 4}
S4: producer thực thi count = register1 {count = 6 }
S5: consumer thực thi count = register2 {count = 4}
Nguyên lý hệ điều hành
6.7
Nguyễn Đức Thịnh - ĐHNNHN
Giải pháp cho Vấn đề Critical Section
1. Mutual Exclusion – Nếu process Pi đang thực thi trong critical section
của nó, thì không có process nào khác được thực thi trong critical
section (của process đó).
2. Tiến độ (progress) – Nếu không có process nào đang thực thi trong
critical section và có một số process yêu cầu được vào critical section
của nó, thì sự lựa chọn process sẽ vào critical section không được
phép trì hoãn mãi.
3. Thời gian chờ đợi bị chặn (Bounded Waiting) – Số lần mà các process
khác được vào critical section sau khi một process yêu cầu được vào
critical section và trước khi yêu cầu đó được chấp thuận phải bị chặn.
Nguyên lý hệ điều hành
Giả sử rằng các process đều đang trong trạng thái thực thi
Không có giả sử nào liên quan tới tốc độ tương đối của N
process đó
6.8
Nguyễn Đức Thịnh - ĐHNNHN
Giải pháp Peterson
Cho hai process
Giả sử rằng các chỉ thị LOAD và STORE là nguyên tố; không thể bị
ngắt.
Hai processes chia sẻ 2 biến:
int turn;
boolean flag[2];
Biến turn chỉ định process nào được vào critical section.
Mảng flag được dùng để thông báo khi nào một process sẵn sàng
vào critical section. flag[i] = true khi process Pi sẵn sàng.
Nguyên lý hệ điều hành
6.9
Nguyễn Đức Thịnh - ĐHNNHN
Thuật toán cho process Pi
do {
flag[i] = TRUE;
turn = j;
while (flag[j] && turn == j);
critical section
flag[i] = FALSE;
remainder section
} while (TRUE);
Nguyên lý hệ điều hành
6.10
Nguyễn Đức Thịnh - ĐHNNHN
Phần cứng đồng bộ hóa
Nhiều hệ thống cung cấp phần cứng hỗ trợ critical section
Đơn bộ xử lý – có thể vô hiệu hóa ngắt
Code đang chạy không thể bị tạm ngừng
Không hiệu quả trên các hệ đa xử lý
OS sử dụng cách này khó mở rộng
Các máy tính hiện đại cung cấp chỉ thị phần cứng nguyên tố
Nguyên tố = không thể ngắt được
Có thể là kiểm tra một từ nhớ hoặc thiết lập giá trị
Hoặc hoán đổi nội dung của hai từ nhớ
Nguyên lý hệ điều hành
6.11
Nguyễn Đức Thịnh - ĐHNNHN
Giải pháp cho Critical-section
Problem sử dụng Locks
do {
acquire lock
critical section
release lock
remainder section
} while (TRUE);
Nguyên lý hệ điều hành
6.12
Nguyễn Đức Thịnh - ĐHNNHN
Chỉ thị TestAndSet
Định nghĩa:
boolean TestAndSet (boolean *target)
{
boolean rv = *target;
*target = TRUE;
return rv:
}
Nguyên lý hệ điều hành
6.13
Nguyễn Đức Thịnh - ĐHNNHN
Giải pháp sử dụng TestAndSet
Biến boolean chia sẻ được dùng làm khóa, khởi tạo bằng
false.
Giải pháp:
do {
while ( TestAndSet (&lock ))
; // do nothing
//
critical section
lock = FALSE;
//
remainder section
} while (TRUE);
Nguyên lý hệ điều hành
6.14
Nguyễn Đức Thịnh - ĐHNNHN
Chỉ thị Swap
Định nghĩa:
void Swap (boolean *a, boolean *b)
{
boolean temp = *a;
*a = *b;
*b = temp:
}
Nguyên lý hệ điều hành
6.15
Nguyễn Đức Thịnh - ĐHNNHN
Giải pháp sử dụng Swap
Biến khóa boolean chia sẻ được khởi tạo bằng FALSE; mỗi process
có một biến chìa khóa địa phương
Giải pháp:
do {
key = TRUE;
while ( key == TRUE)
Swap (&lock, &key );
//
critical section
lock = FALSE;
//
remainder section
} while (TRUE);
Nguyên lý hệ điều hành
6.16
Nguyễn Đức Thịnh - ĐHNNHN
Mutual Exclusion với TestandSet()
do {
waiting[i] = TRUE;
key = TRUE;
while (waiting[i] && key)
key = TestAndSet(&lock);
waiting[i] = FALSE;
// critical section
j = (i + 1) % n;
while ((j != i) && !waiting[j])
j = (j + 1) % n;
if (j == i)
lock = FALSE;
else
waiting[j] = FALSE;
// remainder section
} while (TRUE);
Nguyên lý hệ điều hành
6.17
Nguyễn Đức Thịnh - ĐHNNHN
Semaphore
Công cụ đồng bộ hóa không yêu cầu busy waiting
Semaphore S – biến nguyên
Hai thao tác cơ bản để thay đổi S: wait() và signal()
Chỉ có thể truy cập thông qua hai thao tác nguyên tố:
wait (S) {
while S <= 0
; // no-op
S--;
}
signal (S) {
S++;
}
Nguyên lý hệ điều hành
6.18
Nguyễn Đức Thịnh - ĐHNNHN
Semaphore được dùng
như công cụ đồng bộ hóa tổng quát
Semaphore đếm – giá trị nguyên không bị giới hạn
Semaphore nhị phân – nhận hai giá trị 0 và 1 còn được gọi là mutex lock
Có thể cài đặt một semaphore đếm như một semaphore nhị phân
Cung cấp mutual exclusion
Semaphore mutex;
// initialized to 1
do {
wait (mutex);
// Critical Section
signal (mutex);
// remainder section
} while (TRUE);
Nguyên lý hệ điều hành
6.19
Nguyễn Đức Thịnh - ĐHNNHN
Cài đặt Semaphore
Phải đảm bảo rằng không có hai process nào có thể thực thi wait() và
signal() trên cùng một semaphore tại cùng thời điểm
Như vậy, cài đặt trở thành critical section problem khi wait và signal
được đặt trong critical section.
Có thể xảy ra busy waiting trong cài đặt critical section
Nhưng cài đặt ngắn gọn
Thời gian busy waiting trong critical section ít xảy ra
Chú ý rằng ứng dụng có thể dùng nhiều thời gian trong critical section
và do đó đây không phải là cài đặt tốt.
Nguyên lý hệ điều hành
6.20
Nguyễn Đức Thịnh - ĐHNNHN
Cài đặt Semaphore
không có Busy waiting
Với mỗi semaphore có một waiting queue gắn với nó. Mỗi entry
trong một waiting queue có hai data item:
giá trị (kiểu nguyên)
con trỏ tới phần tử kế tiếp trong danh sách
Hai thao tác:
block – đặt tiến trình gọi nó vào waiting queue thích hợp.
wakeup – gỡ bỏ một tiến trình trong waiting queue và đặt nó vào
ready queue.
Nguyên lý hệ điều hành
6.21
Nguyễn Đức Thịnh - ĐHNNHN
Cài đặt Semaphore không có Busy waiting
Cài đặt của wait:
wait(semaphore *S) {
S->value--;
if (S->value < 0) {
add this process to S->list;
block();
}
}
Cài đặt của signal:
signal(semaphore *S) {
S->value++;
if (S->value <= 0) {
remove a process P from S->list;
wakeup(P);
}
}
Nguyên lý hệ điều hành
6.22
Nguyễn Đức Thịnh - ĐHNNHN
Deadlock và Starvation
Deadlock – hai process chờ vô hạn một event chỉ có thể được gây ra bởi một
trong số các process đó.
Giả sử S và Q là hai semaphore được khởi tạo bằng 1
P0
P1
wait (S);
wait (Q);
wait (Q);
wait (S);
.
.
.
.
.
.
signal (S);
signal (Q);
signal (Q);
signal (S);
Starvation –block vô thời hạn. Một process có thể không bao giờ được gỡ bỏ
khỏi semaphore queue mà nó đang bị tạm ngừng trong đó
Priority Inversion – vấn đề lập lịch khi process có độ ưu tiên thấp giữ khóa
cần thiết cho process có độ ưu tiên cao hơn.
Nguyên lý hệ điều hành
6.23
Nguyễn Đức Thịnh - ĐHNNHN
Các vấn đề cổ điển trong đồng bộ hóa
Vấn đề Bounded-Buffer
Vấn đề Reader và Writer
Vấn đề Dining-Philosopher
Nguyên lý hệ điều hành
6.24
Nguyễn Đức Thịnh - ĐHNNHN
Vấn đề Bounded-Buffer
N buffer, mỗi buffer lưu một item
Semaphore mutex được khởi tạo bằng 1
Semaphore full được khởi tạo bằng 0
Semaphore empty được khởi tạo bằng N.
Nguyên lý hệ điều hành
6.25
Nguyễn Đức Thịnh - ĐHNNHN
Vấn đề Bounded Buffer
Producer process
do {
// produce an item in nextp
wait (empty);
wait (mutex);
// add the item to the buffer
signal (mutex);
signal (full);
} while (TRUE);
Nguyên lý hệ điều hành
6.26
Nguyễn Đức Thịnh - ĐHNNHN
Vấn đề Bounded Buffer
Consumer process
do {
wait (full);
wait (mutex);
// remove an item from buffer to nextc
signal (mutex);
signal (empty);
// consume the item in nextc
} while (TRUE);
Nguyên lý hệ điều hành
6.27
Nguyễn Đức Thịnh - ĐHNNHN
Vấn đề Reader-Writer
Một tập dữ liệu được chia sẻ bởi các process chạy song song.
Reader – chỉ đọc dữ liệu
Writers – có thể đọc và ghi
Vấn đề – cho phép nhiều reader đọc đồng thời. Chỉ có một writer có
thể truy cập dữ liệu chia sẻ tại mỗi thời điểm.
Dữ liệu chia sẻ
Tập dữ liệu
Semaphore mutex khởi tạo bằng 1
Semaphore wrt khởi tạo bằng 1
Số nguyên readcount khởi tạo bằng 0
Nguyên lý hệ điều hành
6.28
Nguyễn Đức Thịnh - ĐHNNHN
Vấn đề Reader-Writer
Writer process
do {
wait (wrt) ;
//
writing is performed
signal (wrt) ;
} while (TRUE);
Nguyên lý hệ điều hành
6.29
Nguyễn Đức Thịnh - ĐHNNHN
Vấn đề Reader-Writer
Reader process
do {
wait (mutex) ;
readcount ++ ;
if (readcount == 1)
wait (wrt) ;
signal (mutex)
// reading is performed
wait (mutex) ;
readcount - - ;
if (readcount == 0)
signal (wrt) ;
signal (mutex) ;
} while (TRUE);
Nguyên lý hệ điều hành
6.30
Nguyễn Đức Thịnh - ĐHNNHN
Vấn đề Dining-Philosopher
Dữ liệu chia sẻ
Bát cơm (data set)
Semaphore chopstick [5] khởi tạo bằng 1
Nguyên lý hệ điều hành
6.31
Nguyễn Đức Thịnh - ĐHNNHN
Vấn đề Dining-Philosophers
Philosopher i:
do {
wait ( chopstick[i] );
wait ( chopStick[ (i + 1) % 5] );
// critical section
signal ( chopstick[i] );
signal (chopstick[ (i + 1) % 5] );
// remainder section
} while (TRUE);
Nguyên lý hệ điều hành
6.32
Nguyễn Đức Thịnh - ĐHNNHN
Vấn đề về Semaphores
Cách dùng không đúng các semaphore operation:
signal (mutex) …. wait (mutex)
wait (mutex) … wait (mutex)
Bỏ qua wait (mutex) hoặc signal (mutex) hoặc cả hai
Nguyên lý hệ điều hành
6.33
Nguyễn Đức Thịnh - ĐHNNHN
Monitor
Một công cụ hiệu quả và tiện lợi để đồng bộ hóa tiến trình
Chỉ một process có thể chạy trong monitor tại mỗi thời điểm
monitor monitor-name
{
// shared variable declarations
procedure P1 (…) { …. }
…
procedure Pn (…) {……}
Initialization code ( ….) { … }
…
}
}
Nguyên lý hệ điều hành
6.34
Nguyễn Đức Thịnh - ĐHNNHN
Sơ đồ của Monitor
Nguyên lý hệ điều hành
6.35
Nguyễn Đức Thịnh - ĐHNNHN
Biến điều kiện
Điều kiện x, y;
Hai thao tác trên biến điều kiện:
x.wait () – tạm ngừng process gọi hàm này.
x.signal () – khôi phục một process (nếu có) đã
gọi x.wait ()
Nguyên lý hệ điều hành
6.36
Nguyễn Đức Thịnh - ĐHNNHN
Monitor với các biến điều kiện
Nguyên lý hệ điều hành
6.37
Nguyễn Đức Thịnh - ĐHNNHN
Giải pháp cho Dining Philosophers
monitor DP
{
enum {THINKING; HUNGRY, EATING} state [5] ;
condition self [5];
void pickup (int i) {
state[i] = HUNGRY;
test(i);
if (state[i] != EATING) self [i].wait;
}
void putdown (int i) {
state[i] = THINKING;
// test left and right neighbors
test((i + 4) % 5);
test((i + 1) % 5);
}
Nguyên lý hệ điều hành
6.38
Nguyễn Đức Thịnh - ĐHNNHN
Giải pháp cho Dining Philosophers
void test (int i) {
if ( (state[(i + 4) % 5] != EATING) &&
(state[i] == HUNGRY) &&
(state[(i + 1) % 5] != EATING) ) {
state[i] = EATING ;
self[i].signal () ;
}
}
initialization_code() {
for (int i = 0; i < 5; i++)
state[i] = THINKING;
}
}
Nguyên lý hệ điều hành
6.39
Nguyễn Đức Thịnh - ĐHNNHN
Giải pháp cho Dining Philosophers
Mỗi philosopher i gọi các hàm pickup() và putdown() theo thứ tự sau:
DiningPhilosophters.pickup (i);
EAT
DiningPhilosophers.putdown (i);
Nguyên lý hệ điều hành
6.40
Nguyễn Đức Thịnh - ĐHNNHN
Cài đặt Monitor Sử dụng Semaphores
Biến
semaphore mutex; // (khởi tạo = 1)
semaphore next; // (khởi tạo = 0)
int next-count = 0;
Mỗi thủ tục F được thay thế bởi:
wait(mutex);
…
body of F;
…
if (next_count > 0)
signal(next)
else
signal(mutex);
Mutual exclusion trong một monitor được đảm bảo.
Nguyên lý hệ điều hành
6.41
Nguyễn Đức Thịnh - ĐHNNHN
Cài đặt Monitor
Với mỗi biến điều kiện x, ta có:
semaphore x_sem; // (khởi tạo = 0)
int x-count = 0;
Thao tác x.wait có thể được cài đặt như sau:
x-count++;
if (next_count > 0)
signal(next);
else
signal(mutex);
wait(x_sem);
x-count--;
Nguyên lý hệ điều hành
6.42
Nguyễn Đức Thịnh - ĐHNNHN
Cài đặt Monitor
Thao tác x.signal can be implemented as:
if (x-count > 0) {
next_count++;
signal(x_sem);
wait(next);
next_count--;
}
Nguyên lý hệ điều hành
6.43
Nguyễn Đức Thịnh - ĐHNNHN
Monitor dùng cho cấp phát tài nguyên
monitor ResourceAllocator
{
boolean busy;
condition x;
void acquire(int time) {
if (busy)
x.wait(time);
busy = TRUE;
}
void release() {
busy = FALSE;
x.signal();
}
initialization code() {
busy = FALSE;
}
}
Nguyên lý hệ điều hành
6.44
Nguyễn Đức Thịnh - ĐHNNHN
Ví dụ đồng bộ hóa
Solaris
Windows XP
Linux
Pthreads
Nguyên lý hệ điều hành
6.45
Nguyễn Đức Thịnh - ĐHNNHN
Đồng bộ hóa trong Solaris
Cài đặt một số khóa hỗ trợ đa nhiệm, đa luồng (bao gồm các luồng
thời gian thực), và đa bộ xử lý
Sử dụng các adaptive mutex để tăng tính hiệu quả khi bảo vệ dữ liệu
khỏi các code segment ngắn
Sử dụng các biến điều kiện và reader-writer lock khi các code
segment dài hơn yêu cầu truy cập dữ liệu
Sử dụng turnstiles để sắp xếp danh sách các luồng đang chờ để
nhận được hoặc một adaptive mutex hoặc reader-writer lock
Nguyên lý hệ điều hành
6.46
Nguyễn Đức Thịnh - ĐHNNHN
Đồng bộ hóa trong Windows XP
Sử dụng mặt nạ ngắt (interrupt masks) để ngăn cản các truy cập tới
tài nguyên hệ thống trong các hệ đơn bộ xử lý
Sử dụng spinlocks trong các hệ đa bộ xử lý
Cung cấp các dispatcher object hoạt động như mutex và
semaphore
Dispatcher object có thể còn cung cấp event
Một event hoạt động tương tư như một biến điều kiện
Nguyên lý hệ điều hành
6.47
Nguyễn Đức Thịnh - ĐHNNHN
Linux Synchronization
Linux:
Trước khi có nhân version 2.6, vô hiệu hóa interrupt để cài đặt các
critical section ngắn
Từ version 2.6 về sau, hoàn toàn preemptive
Linux cung cấp:
semaphore
spin lock
Nguyên lý hệ điều hành
6.48
Nguyễn Đức Thịnh - ĐHNNHN
Pthreads Synchronization
Pthreads API độc lập với OS
Các chức năng:
mutex lock
condition variable
Các mở rộng non-portable còn bao gồm:
read-write lock
spin lock
Nguyên lý hệ điều hành
6.49
Nguyễn Đức Thịnh - ĐHNNHN
Hết chương 6
Nguyên lý hệ điều hành
Nguyễn Đức Thịnh - ĐHNNHN