Bài giảng Nguyên lý ngôn ngữ lập trình - Chương 9: Ngôn ngữ lập trình song song - Nguyễn Văn Hòa

Tóm tắt Bài giảng Nguyên lý ngôn ngữ lập trình - Chương 9: Ngôn ngữ lập trình song song - Nguyễn Văn Hòa: ...ủộng? 16 Tương tranh ở mức CT con (tt)  Cỏc phương thức ủồng bộ húa: 1. Semaphores 2. Chương trỡnh giỏm sỏt (Monitors) 3. Truyền thụng ủiệp (Message Passing) 17 Semaphores  Dijkstra - 1965  Một semaphore là một cấu trỳc dữ liệu chứa một counter và một hàng ủợi (queue) nhằm lưu trữ cỏ...anh)  Counter của access sẽ chỉ cú hai giỏ trị 0 và 1  Tương ủương như là một semaphore nhị phõn (binary semaphore)  Giỏ trị khởi tạo của access phải là 1, ủồng nghĩa là tài nguyờn ủang ở trạng thỏi sẵn sàng. 0 nghĩa là bận 26 Code của Producer-Consumer semaphore access, fullspots, empt... BS, BS sẽ khỏm bệnh cho bệnh nhõn nếu cả hai ủều rónh  Hoặc lấy cỏi hẹn 35 Truyền thụng ủiệp (tt)  Truyền thụng ủiệp là mụ hỡnh tương tranh  Cú thể là mụ hỡnh của cả semaphore và CT giỏm sỏt  Khụng chỉ cho ủồng bộ húa cạnh tranh  Truyền thụng ủiệp ủồng bộ, khi bận cỏc task khụng muố...

pdf52 trang | Chia sẻ: havih72 | Lượt xem: 301 | Lượt tải: 0download
Nội dung tài liệu Bài giảng Nguyên lý ngôn ngữ lập trình - Chương 9: Ngôn ngữ lập trình song song - Nguyễn Văn Hòa, để tải tài liệu về máy bạn click vào nút DOWNLOAD ở trên
1Chương 9: Ngơn ngữ lập 
trình song song
Giảng viên: Ph.D Nguyễn Văn Hịa
Khoa KT-CN-MT – ðH An Giang
2Nội dung
 Giới thiệu
 SubProprogam-level
 Semaphores
 Chương trình giám sát (monitor)
 Truyền thơng điệp (massage passing) 
 Luồng (Java thread)
3Giới thiệu
 Sự tương tranh (concurrency) cĩ thể xảy ra ở 4 
mức sau:
1. Lệnh mã máy
2. Câu lệnh của NN LT cấp cao (lệnh lặp)
3. Chương trình con
4. Chương trình
 Vì khơng cĩ một NN LT nào hỗ trợ tương tranh ở 
mức chương trình, và lệnh mã máy nên 2 sự 
tương tranh này khơng được trình bày ở chương 
này
4Giới thiệu (tt)
 ðN: Thread điều khiển trong một chương trình là 
thứ tự các điểm cần đến của CT
 Phân loại sự tương tranh:
1. Tương tranh vật lý (physical concurrency) – Multiple 
processors độc lập (điều khiển với multiple threads)
2. Trương tranh logic (logical concurrency) – Sự tương 
tranh này xuất hiện khi cĩ sự chia sẽ trên cùng một 
processor (Một phần mền cĩ thể được thiết kết với 
multiple thread)
5Giới thiệu (tt)
 Tại sao phải học sự tương tranh trong NN LT
1. Rất hữu dụng cho việc thiết kế chương trình hỗ trợ 
tính tốn song song
2. Máy tính hỗ trợ tương tranh vật lý (multi-core 
processors) rất phổ biến
6Kiến trúc máy tính multi-core
Single instruction 
multiple data (SIMD)
Multiple Instruction 
multiple data (MIMD)
7Tương tranh ở mức chương trình con
 ðN: Một cơng việc (task) hoặc tiến trình (process) là một 
đơn vị chương trình được thực hiện đồng thời với những 
chương trình khác
 Task khác với chương trình con như thế nào?
 Task cĩ thể được bắt đầu ở thời điểm tường minh
 Khi một chương trình bắt đầu thực thi một task, thơng thường thì
khơng bị đình hỗn
 Khi việc thực thi một task kết thúc thì khơng nhất thiết phải trả 
quyền điều khiển cho caller
 Các cơng việc (tasks) cĩ thể trao đổi qua lại
8Tương tranh ở mức CT con (tt)
 Thơng thường cĩ 2 loại tasks
 Heavyweight tasks thực thi với khơng gian địa chỉ và 
run-time stack của chính nĩ
 Lightweight tasks luơn luơn thực thi với cùng khơng 
gian địa chỉ và cùng run-time stack
9Tương tranh ở mức CT con (tt)
 ðN: một task riêng biệt (disjoint) nếu như nĩ 
khơng giao tiếp hoặc ảnh hường đến sự thực thi 
của một task nào đĩ trong một chương trình bất 
kỳ
 Một task giao tiếp với một task khác thì cần 
thiết phải cĩ sự đồng bộ hĩa (synchronization)
 Sự giao tiếp cĩ thể bằng:
1. Chia sẽ các biến khơng cục bộ
2. Tham số
3. Truyền thơng điệp
10
Tương tranh ở mức CT con (tt)
 Các kiểu đồng bộ hĩa :
1. Hợp tác (Cooperation)
 Task A phải đợi cho đến khi task B hồn thành một vài 
tác vụ nhất định nào đĩ trước khi task A cĩ thể thực hiện 
tiếp tục → mơ hình producer-consumer
2. Cạnh tranh (competition)
 Khi hai hoặc nhiều tasks cùng dùng chung một tài nguyên 
(resource) nhưng tài nguyên này khơng thể dùng đồng 
thời được
 Sự canh tranh thường được cung cấp bởi quyền truy cập 
loại trừ lẫn nhau
11
Sự cần thiết của đơng bộ hĩa 
trong cạnh tranh
12
Tương tranh ở mức CT con (tt)
 Việc đồng bộ hĩa địi hỏi một cơ chế của sự trị 
hỗn việc thực thi các task
 Sự điều khiển việc thực thi được điều hành bởi 
một chương trình, gọi là scheduler, cĩ nhiệu vụ 
sắp đặt việc thực thi task vào những processors 
sẵn cĩ
13
Tương tranh ở mức CT con (tt)
 Các Task cĩ thể ở một trong vài trạng thái sau 
đây:
1. New – mới khởi tạo nhưng chưa được thực hiện
2. Runnable hoặc ready – sẵn sàng để chạy nhưng chưa 
chạy (vì khơng cĩ processor sẵn cĩ)
3. Running 
4. Blocked – đã chạy, nhưng khơng thể tiếp tục vì đang 
đợi vài sự kiện nào đĩ xảy ra)
5. Dead
14
Tương tranh ở mức CT con (tt)
 Liveness là đặc điểm mà một chương trình cĩ thể 
cĩ hoặc khơng
 Trong code tuần tự, nghĩa là nếu một CT tiếp tục thực 
thi → dẫn đến sự cạnh tranh
 Trong mơi trường tương tranh, một task cĩ thể dễ dàng 
mất liveness của nĩ
 Nếu tất cả các task trong mơi trường tương tranh đều 
mất liveness của chúng, trường hợp này gọi là 
deadlock
15
Tương tranh ở mức CT con (tt)
 Các NN LT hỗ trợ tương tranh đều cĩ 2 cơ chế: 
đồng bộ hĩa cạnh tranh và đồng bộ hĩa hợp tác 
 Các yếu tố khi thiết kế tương tranh:
1. Sự đồng bộ hĩa hợp tác được cung cấp như thế nào?
2. Sự đồng bộ hĩa tương tranh được cung cấp như thế 
nào?
3. Cách gì và khi nào một task bắt đầu và kết thúc thực 
thi?
4. Các task cĩ được sinh ra một cách tĩnh hay động?
16
Tương tranh ở mức CT con (tt)
 Các phương thức đồng bộ hĩa:
1. Semaphores
2. Chương trình giám sát (Monitors)
3. Truyền thơng điệp (Message Passing)
17
Semaphores 
 Dijkstra - 1965
 Một semaphore là một cấu trúc dữ liệu chứa một 
counter và một hàng đợi (queue) nhằm lưu trữ các 
mơ tả của task
 Các semaphores được dùng để cài đặt các bảo vệ 
trong code cĩ sự truy nhập các cấu trúc dữ liệu 
chia sẽ
 Các semaphores chỉ cĩ 2 thao tác vụ, wait và
release (hay được gọi P và V bởi Dijkstra)
 Các semaphores cĩ thể được dùng trong cả đồng 
bộ hĩa cạnh tranh và hợp tác
18
Semaphores
 ðồng bộ hĩa hợp tác với Semaphores
 Example: Một buffer chia sẽ
 Buffer được cài đặt với hai tác vụ DEPOSIT và
FETCH như là hai cách thức để truy nhập buffer
 Sử dụng hai semaphores cho sự hợp tác:
emptyspots và fullspots
 Counter của hai semaphore dùng để lưu trữ số empty
spots và full spots trong buffer
19
Semaphores
 Trước tiên DEPOSIT phải kiểm tra 
emptyspots xem cĩ cịn khoảng trống trong 
buffer khơng
 Nếu cịn khoảng trống thì counter của emtyspots 
giảm đi một và giá trị được đưa vào buffer
 Nếu khơng cịn khoảng trống thì chương trình gọi 
DEPOSIT được đặt trong hàng đợi cho đến khi cĩ 
một emtyp spot rỗng
 Khi kết thúc DEPOSIT, giá trị của counter của 
fullspots được tăng lên một
20
Semaphores
 Trước tiên FETCH phải kiểm tra fullspots
xem cĩ cịn giá trị nào trong buffer khơng
 Nếu cịn thì một giá trị được lấy ra và counter của 
fullspots bị giảm đi một
 Nếu khơng cịn giá trị nào thì tiến trình của FETCH 
được đặt trong hàng đợi cho đến khi cĩ một giá trị xuất 
hiện
 Khi kết thúc FETCH, tăng counter của emptyspots 
lên một
 Hai thao tác FETCH và DEPOSIT trên các 
semaphore thành cơng thơng qua hai thao tác wait
và release
21
Semaphores
wait(aSemaphore)
if aSemaphore’s counter > 0 then
Decrement aSemaphore’s counter
else
Put the caller in aSemaphore’s queue
Attempt to transfer control to some
ready task 
(If the task ready queue is empty, 
deadlock occurs) 
end
22
Semaphores
release(aSemaphore)
if aSemaphore’s queue is empty {no one waiting}
then
Increment aSemaphore’s counter
else
Put the calling task in the task ready 
queue
Transfer control to a task from
aSemaphore’s queue
end
23
Producer Consumer Code
semaphore fullspots, emptyspots;
fullspots.count = 0;
emptyspots.count = BUFLEN;
task producer;
loop
-- produce VALUE –-
wait (emptyspots); {wait for space}
DEPOSIT(VALUE);
release(fullspots); {increase 
filled}
end loop;
end producer;
24
Producer Consumer Code
task consumer;
loop
wait (fullspots);{to make sure it is not empty}
FETCH(VALUE);
release(emptyspots); {increase empty space}
-- consume VALUE –-
end loop;
end consumer;
25
Semaphores
 ðồng bộ hĩa cạnh tranh với semaphores
 Semaphore thứ ba, cĩ tên là access, dùng để kiểm 
sốt truy cập (đồng bộ hĩa cạnh tranh)
 Counter của access sẽ chỉ cĩ hai giá trị 0 và 1
 Tương đương như là một semaphore nhị phân (binary
semaphore)
 Giá trị khởi tạo của access phải là 1, đồng nghĩa là 
tài nguyên đang ở trạng thái sẵn sàng. 0 nghĩa là bận
26
Code của Producer-Consumer 
semaphore access, fullspots, emptyspots;
access.count = 1;
fullstops.count = 0;
emptyspots.count = BUFLEN;
task producer;
loop
-- produce VALUE –-
wait(emptyspots); {wait for space}
wait(access); {wait for access)
DEPOSIT(VALUE);
release(access); {relinquish access}
release(fullspots); {increase filled space}
end loop;
end producer;
27
Code của Producer-Consumer
task consumer;
loop
wait(fullspots);{make sure it is not empty}
wait(access); {wait for access}
FETCH(VALUE);
release(access); {relinquish access}
release(emptyspots); {increase empty space}
-- consume VALUE –-
end loop;
end consumer;
28
Semaphores : nhận xét
 Mơi trường lập trình khơng an tồn (Unsafe)
 Sử dụng sai các semaphores cĩ thể là nguyên nhân thất 
bại trong đồng bộ hĩa hợp tác, e.g., buffer sẽ bị tràn 
(overflow) nếu khơng cĩ dịng code 
wait(emptyspots) trong producer task. Hoặc 
buffer sẽ bị underflow nếu khơng cĩ dịng code 
wait(fullspots)
 Trình biên dịch khơng thể kiểm tra việc dùng sai
 Sự tin cậy
 Sử dụng sai cĩ thể là nguyên nhân thất bại của đồng bộ 
hĩa cạnh tranh, e.g., chương trình sẽ bị deadlock nếu 
loại bỏ dịng code release(access)
29
Chương trình giám sát (Monitors)
 NNLT : concurrent Pascal, Modula, Mesa, tiếp 
theo là C#, Ada and Java
 Ý tưởng: bao đống dữ liệu chia sẽ và giới hạn các 
thao tác truy nhập
 CT giám sát là một trù tường hĩa dữ liệu cho 
những dữ liệu chia sẽ
30
Monitor Buffer Operation
31
ðồng bộ hĩa cạnh tranh
 Dữ liệu chia sẽ được đặt bên trong CT giám sát
(tốt hơn là đặt trong các client)
 Tất cả các truy nhập đều diễn ra ở trong CT giám 
sát
 Việc cài đặt CT giám sát phải bảo đảm các truy cập 
được đồng bộ bằng cách chỉ cĩ một truy cập tại một 
thời điểm nhất định
 Nếu CT giám sát bận vào thời điểm gọi, thì các lời gọi 
sẽ được đặt vào trong hàng đợi
32
ðồng bộ hĩa hợp tác
 Sự hợp tác giữa các tiến trình (processes) vẫn là 
một tác vụ trong lập trình
 Lập trình viên phải bảo đảm là khơng xảy ra underflow
và overflow trong một buffer chia sẽ
33
Chương Trình giám sát: nhận xét
 Hỗ trợ tốt cho sự đồng bộ hĩa cạnh tranh
 ðối với đồng bộ hĩa hợp tác thì tương tự như 
semaphore nên → sẽ gặp các vấn đề như 
semaphore
34
Truyền thơng điệp
 ðược đưa ra bởi Hansen & Hoare vào 1978
 Vấn đề: làm thế nào giải quyết vấn đề khi cĩ nhiều 
yêu cầu giao tiếp từ nhiều task với một task cho trước
 Vài dạng của cơ chế khơng quyết định cho sự cơng bằng
 Guarded commands của Dijkstra: kiểm sốt truyền thơng 
điệp
 Ý tưởng chính: giao tiếp giữa các task giống như đến 
phịng mạch
 Phần lớn thời gian BS đợi bệnh nhân 
 Hoặc bệnh nhân đợi BS, BS sẽ khám bệnh cho bệnh nhân 
nếu cả hai đều rãnh
 Hoặc lấy cái hẹn
35
Truyền thơng điệp (tt)
 Truyền thơng điệp là mơ hình tương tranh
 Cĩ thể là mơ hình của cả semaphore và CT giám sát
 Khơng chỉ cho đồng bộ hĩa cạnh tranh
 Truyền thơng điệp đồng bộ, khi bận các task khơng 
muốn bị gián đoạn
36
Truyền thơng điệp
 Trong phạm vi tasks, chúng ta cần:
a. Một cơ chế để cho phép một task biểu thị khi nào nĩ 
sẵn sàng nhận các thơng điệp
b. Các tasks cần cách ghi nhớ các task khác đang đợi nĩ 
nhận message và cĩ sự lựa chọn các message tiếp theo
 ðN: Khi message của một task được nhận bởi 
một task nào đĩ, thì sự truyền message được gọi 
là rendezvous
37
VD về Rendezvous
38
Tương tranh trong Java: Java thread 
 Khi chương trình Java thực thi hàm main() tức là 
tạo ra một luồng chính (main thread)
 Trong luồng main
 Cĩ thể tạo các luồng con
 Khi luồng main ngừng thực thi, chương trình sẽ kết 
thúc 
 Luồng cĩ thể được tạo ra bằng 2 cách:
 Tạo lớp dẫn xuất từ lớp Thread
 Tạo lớp hiện thực giao tiếp Runnable
39
Tương tranh trong Java (tt)
 VD
public class Mythread extends Thread{
private String data
public Mythread(String data){
this.data = data;
}
public void run(){
System.out.println(‘‘I am a thread!’’);
System.out.println(‘‘The data is:’’,data);
}
}
40
Tương tranh trong Java (tt)
 Tạo ra một thể hiện của lớp Thread (hoặc dẫn xuất của nĩ) 
và gọi phương thức start()
 Khi gọi myThread.start() một luồng mới tạo ra và chạy 
phương thức run() của myThread.
41
Tương tranh trong Java: Runnable
 Giao tiếp Runnable
 Ngồi tạo luồng bằng cách thừa kế từ lớp Thread, cũng 
cĩ một cách khác để tạo luồng trong Java
 Luồng cĩ thể tạo bằng cách tạo lớp mới hiện thực giao 
tiếp Runnable và định nghĩa phương thức: 
public abstract void run()
 ðiều này đặc biệt hữu ích nếu muốn để tạo ra một đối 
tượng Thread nhưng muốn sử dụng một lớp cơ sở khác 
Thread
42
Tương tranh trong Java: Runnable
 VD
43
Tương tranh trong Java: Runnable
 ðể tạo ra một luồng mới từ một đối tượng hiện thực giao 
tiếp Runnable, cần phải khởi tạo một đối tượng Thread
mới với đối tượng Runnable như đích của nĩ
 Khi gọi start() trên đối tượng luồng sẽ tạo ra một luồng 
mới và phương thức run() của đối tượng Runnable sẽ 
được thực hiện
44
Tương tranh trong Java: điều khiển
45
Tương tranh trong Java: điều khiển
 Khi một luồng giành quyền sử dụng CPU, nĩ sẽ thực hiện 
cho đến khi một sự kiện sau xuất hiện:
 Phương thức run() kết thúc
 Một luồng quyền ưu tiên cao hơn 
 Nĩ gọi phương thức sleep() hay yield() – nhượng bộ
 Khi gọi yield(), luồng đưa cho các luồng khác với cùng 
quyền ưu tiên cơ hội sử dụng CPU. Nếu khơng cĩ luồng 
nào khác cùng quyền ưu tiên tồn tại, luồng tiếp tục thực 
hiện
 Khi gọi sleep(), luồng ngủ trong một số mili-giây xác 
định, trong thời gian đĩ bất kỳ luồng nào khác cĩ thể sử 
dụng CPU
46
Tương tranh trong Java: điều khiển
 Phương thức join()
 Khi một luồng (A) gọi phương thức join() của một 
luồng nào đĩ (B), luồng hiện hành (A) sẽ bị khĩa chờ 
(blocked) cho đến khi luồng đĩ kết thúc (B).
47
ðồng bộ hĩa cạnh tranh với java
 Dùng từ khĩa synchronized trước tên các hàm khi 
định nghĩa để cấm các lớp khác thực thi các hàm 
này khi nĩ đang thực thi
class ManageBuf{
private int [100] buf;
public synchonized void deposit(int item){}
public synchonized void fetch(int item){}
}
48
ðồng bộ hĩa hợp tác với java
 Các phương thức wait(), notify() và notifyAll() 
được sử dụng để thĩa khĩa trên một đối tượng và 
thơng báo các luồng đang đợi chúng cĩ thể cĩ lại 
điều khiển
 wait() được gọi trong vịng lập
 notify() thơng báo cho thread đang chờ đợi là sự 
kiện đang đợi đã xãy ra
 notifyall() đánh thức các thread đang đợi là cĩ thể 
thực thi sau lệnh wait() 
49
ðồng bộ hĩa hợp tác với java: VD
50
ðồng bộ hĩa hợp tác với java: VD
51
SimpleThread
class SimpleThread extends Thread {
public SimpleThread(String str) {
super(str);
}
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println(i + " " + getName());
try {
sleep((int)(Math.random() * 1000));
} catch (InterruptedException e) {}
}
System.out.println("DONE! " + getName());
}
}
52
TwoThreads
class TwoThreadsTest {
public static void main (String[] args) {
new SimpleThread("Jamaica").start();
new SimpleThread("Fiji").start();
}
}

File đính kèm:

  • pdfbai_giang_nguyen_ly_ngon_ngu_lap_trinh_chuong_9_ngon_ngu_lap.pdf