You are on page 1of 292

TRƯỜNG ĐẠI HỌC THUỶ LỢI

KHOA CÔNG NGHỆ THÔNG TIN


BỘ MÔN CÔNG NGHỆ PHẦN MỀM

Bài giảng
LẬP TRÌNH PHÂN TÁN

Hà Nội - 09/2021
TRƯỜNG ĐẠI HỌC THUỶ LỢI

Khoa Công Nghệ Thông Tin


Bộ Môn Công Nghệ Phần Mềm

LẬP TRÌNH PHÂN TÁN


50-50, gồm 5 bài thực hành 5 bài LT

Giảng viên: TS. Lê Nguyễn Tuấn Thành


Email: thanhlnt@tlu.edu.vn
ĐT: 0898158945
LẬP
TRÌNH
ĐỒNG TỔNG QUAN
MÔN HỌC
THỜI
&
PHÂN
TÁN Giảng viên: Lê Nguyễn Tuấn Thành
Email: thanhlnt@tlu.edu.vn
Giới thiệu chung
▪Tên môn học: Lập trình Phân tán
▪Tên tiếng Anh: Distributed
Programming
▪Mã môn học: CSE423
▪Số tín chỉ: 3 (LT: 2, TH/BT/TL: 1)
▪Số tiết: 30 - Lý thuyết và 15 - Thực
hành
2
Mục tiêu môn học
▪Cung cấp các kiến thức, bài toán và kỹ
năng cho lập trình đồng thời, lập trình
song song và lập trình phân tán
▪Cung cấp kiến thức nền tảng để phát
triển ứng dụng đồng thời và phân tán

3
Terminology
đồng thời, song song, phân phối
▪ Concurrency, Parallelism, Distribution
▪ Concurrent programming
▪ Thread, Process, Locks, Safety, Liveness,
▪ Deadlock, Livelock, Resource starvation,
▪ Critical section,
▪ Atomic operations/statements and
variables
▪ Synchronization
▪ Semaphore, Monitor

▪ Distributed programming
▪ Clock synchronization
▪ Happened-before
▪ Client-Server, RMI, RPC
▪ Graph theory
4
▪ Bài 1: Những khái niệm cơ sở
▪ Bài 2: Bài toán loại trừ lẫn
nhau
▪ Bài 3: Những cơ sở đồng bộ
hóa
▪ Bài 4: Lập trình phân tán
Nội dung
▪ Bài 5: Mô hình và cơ chế
môn học đồng hồ
▪ Bài 6: Bài toán phân phối tài
nguyên
▪ Bài 7: Kiểu thứ tự thông điệp
▪ Bài 8: Bài toán lựa chọn
người lãnh đạo 5
=> bài thực hành chấm cá nhân
=>> dqt: ktra 15p + thực hành + điểm cộng LT
----->>> thi hết môn: trắc nghiệm giống bài kiểm tra nhỏ

Yêu cầu với sinh viên


▪ Tham dự lớp và nghe giảng đầy đủ
bài thực hành
▪ Thảo luận, làm bài tập trên lớp và Piazza (cộng điểm)
▪ Website môn học: sites.google.com/site/cse423fall2018/
▪ Lớp học ảo:
Text
▪ Cách đánh giá:
▪ Điểm quá trình (chuyên cần + thực hành + điểm cộng): 50%
▪ Điểm thi hết môn (trắc nghiệm): 50%

Labs:
1. làm quen với Thread
2. các thuật toán mutex: giải quyết bài toán loại trừ lẫn nhau
3. semaphore + monitor: khó (lập trình đồng thời)
4. kỹ thuật lập trình socket: chương trình phân tán với socket
5. chương trình phân tán với RPC/RMI (lập trình phân tán)
6
Tài liệu tham khảo
▪ Concurrent and Distributed Computing in Java, Vijay K. Garg,
University of Texas, John Wiley & Sons, 2005
▪ Tham khảo:
▪ Principles of Concurrent and Distributed Programming, M. Ben-Ari,
Second edition, 2006
▪ Foundations of Multithreaded, Parallel, and Distributed
Programming, Gregory R. Andrews, University of Arizona,
Addison-Wesley, 2000
▪ The SR Programming Language: Concurrency in Practice,
Benjamin/Cummings, 1993
▪ Xử lý song song và phân tán, Đoàn văn Ban, Nguyễn Mậu Hân, Nhà
xuất bản Khoa học và Kỹ thuật, 2009.

7
Bài học:
- Hệ thống đồng thời (Thread)

LẬP - Hệ thống phân tán (Process)

TRÌNH
BÀI 1:
ĐỒNG NHỮNG KIẾN
THỜI THỨC CƠ SỞ
& 1
PHÂN
TÁN Giảng viên: Lê Nguyễn Tuấn Thành
Email: thanhlnt@tlu.edu.vn
NỘI DUNG
1. Thuật ngữ
2. Luồng trong Java

Bài giảng có sử dụng hình vẽ trong cuốn sách “Concurrent and Distributed Computing in Java, Vijay K.
Garg, University of Texas, John Wiley & Sons, 2005” 2
Thuật ngữ:
1. Hệ đơn nhiệm
2. Hệ đa nhiệm
3. Tính toán tuần tự
4. Tính toán đồng thời/ song song
Luật Amdahl
5. Tính toán phân tán
6. Chương trình, tiến trình, luồng

3
Phần 1.
Thuật ngữ
Thuật ngữ (1)
▪ Tính toán tuần tự (sequential computing)
▪ Tại một thời điểm chỉ thực hiện được một tính
toán
▪ Chỉ có một luồng điều khiển chính
▪ Hệ thống đơn nhiệm (single-tasking systems)
▪ Hệ thống đa nhiệm (multitasking systems)
▪ Time-slicing

Tại sao phải tính toán đồng thời / song


song?
4
Thuật ngữ (2)
▪ Tính toán đồng thời / song song (concurrent
/ parallel computing): Mô hình chia sẻ bộ nhớ
▪ Tại một thời điểm có thể thực hiện nhiều tính toán
▪ Bao gồm nhiều “chương trình” chạy trên một hoặc
nhiều bộ vi xử lý
▪ Giao tiếp với nhau bằng cách sử dụng bộ nhớ chia
sẻ
▪ Một “chương trình” bất kỳ luôn biết được trạng
thái toàn cục của toàn bộ hệ thống

5
Minh họa:
Hệ thống song song

6
Giả sử: 1 người ≈ 1 Processor
▪ Multitasking:
▪ 1 bạn: vừa làm bài tập (LT+TH)
môn CSE423, vừa nghe nhạc
▪ Concurrency: đồng thời
▪ 1 bạn: vừa đọc phần lý thuyết,
vừa code phần thực hành
▪ Parallelism: song song
▪ 2 bạn: 1 bạn đọc phần lý thuyết,
1 bạn code phần thực hành

7
Thuật ngữ (3)
▪ Tính toán phân tán (distributed computing)
▪ Hệ thống phân tán chứa nhiều bộ xử lý được kết
nối với nhau bởi một mạng truyền thông
▪ Các bộ vi xử lý giao tiếp với nhau bằng cách gửi và
nhận các thông điệp, thông qua các kênh truyền
thông (pipe, socket)
▪ Không có bộ xử lý nào biết được trạng thái toàn
cục của toàn bộ hệ thống phân tán

8
Minh họa:
Hệ thống phân tán

socket…..

9
10
Thuật ngữ (4)
Chương trình (program): một Tiến trình (process): một instance
tập các chỉ lệnh bằng ngôn ngữ của một chương trình đang chạy, có
lập trình không gian bộ nhớ riêng, gồm:
▪ Chương trình tuần tự: thực ▪ Mã chương trình: những chỉ lệnh máy
hiện trong một “tiến trình” trong bộ nhớ mà tiến trình thực thi
duy nhất ▪ Dữ liệu gồm bộ nhớ được sử dụng
▪ Chương trình đồng thời: bởi các biến toàn cục tĩnh và bộ nhớ
được cấp phát trong thời gian chạy
nhiều “tiến trình”
▪ Ngăn xếp gồm các biến địa phương và
các bản ghi kích hoạt lời gọi hàm

Luồng (threads): một tiến trình gồm một hay nhiều luồng.
Các luồng trong cùng một tiến trình chia sẻ tài nguyên (bộ nhớ,
files,…)
Luồng “gọn nhẹ" hơn so với tiến trình và tốn ít phụ phí hơn để tạo và
11
huỷ luồng so với khởi động một tiến trình mới.
12
Minh hoạt luồng 13
Thách thức của các
chương trình đồng thời

Làm sao để đồng bộ việc thực thi của các


tiến trình/luồng khác nhau và cho phép
chúng giao tiếp với nhau ?

14
▪ Giả sử chương trình có 2 luồng:
1. Luồng P bao gồm 2 câu lệnh p1, được theo sau bởi p2
2. Luồng Q bao gồm 2 câu lệnh q1, được theo sau bởi q2
▪ Hai luồng bắt đầu thực thi tại vị trí của con trỏ điều
Interleaving
kiển (control pointer), lúc đầu trỏ tới p1 và q1
▪ Giả sử các câu lệnh không thực hiện việc chuyển
điều khiển khi đang thực thi
▪ Các kịch bản có thể xảy ra ???
1. p1 → q1 → p2 → q2 Interleaving
2. p1 → q1 → q2 → p2
3. p1 → p2 → q1 → q2
4. q1 → p1 → q2 → p2
5. q1 → p1 → p2 → q2
6. q1 → q2 → p1 → p2

▪ p2 → p1 → q1 → q2 có phải là một kịch bản không?


▪ KHÔNG !
▪ Tôn trọng sự thực thi tuần tự của mỗi tiến trình 15
▪ Do đó p2 không thể thực thi trước p1 !
trạng thái đua tranh

Race condition

Giá trị của n là bao nhiêu khi p, q thực thi xong ?


=> có thể =1 hoặc =2, không thể control được giá trị cuối cùng

16
17
Có hai cơ chế để bảo vệ một khối mã lệnh khỏi việc truy cập đồng thời
• Từ khoá synchronized
18
• Lớp ReentrantLock (từ Java SE 5.0)
Concurrency is Hard to
Test and Debug (1)
▪ It’s very hard to discover race conditions using
testing
▪ Each time you run a program containing a race
condition, you may get different behavior !
▪ Interleaving of instructions or messages depends
on the relative timing of events that are strongly
influenced by the environment
▪ Delays can be caused by other running programs,
other network traffic, operating system
scheduling decisions, variations in processor clock
speed, etc.
19
Concurrency is Hard to
Test and Debug (2)
▪ Two kinds of bugs:
1. heisenbugs, which are nondeterministic and hard
to reproduce,
2. bohrbug, which shows up repeatedly whenever
you look at it.
▪ Almost all bugs in sequential programming are
bohrbugs
▪ A heisenbug may even disappear when you try to look
at it with println or debugger !
▪ The reason is that printing and debugging are so much
slower than other operations, often 100-1000x slower,
that they dramatically change the timing of operations,
and the interleaving.

20
Phần 2.
21
Luồng trong
Java
Cách 1: Kế thừa từ lớp Thread (có sẵn trong java)

Hàm run() là hàm mặc định chạy khi được gọi Thread

thực hiện 1 số bước khởi động => sau đó gọi hàm run

2 luồng: main; t
nếu chỉ 1 luồng main: là tuần tự =>. luồng t và luồng main chạy đồng thời với nhau

Tạo luồng bằng cách


kế thừa lớp Thread 22
Cách 2: implements Runnable

Tạo luồng bằng cách cài


đặt giao diện Runnable 23
Các trạng thái của luồng
trong Java
bị chặn

gọi hàm start()


mới tạo có thể chạy chấm dứt

đang chờ đang chờ hết thời gian 24


Cơ chế Join (1)
▪Cho phép một luồng đợi một luồng khác
hoàn thành việc thực thi
▪Ví dụ:
▪ Viết chương trình sử dụng luồng trong
Java để tính số Fibonacci thứ n (Fn) sử
dụng công thức: Fn = Fn-1 + Fn-2 với n ≥ 2
▪ Các trường hợp cơ sở: F0 = 1, F1 = 1

25
Cơ chế Join (2)

26
Lập lịch trình luồng
▪ Nếu cả hai luồng đều có thể chạy, luồng nào
sẽ được chọn để chạy bởi hệ thống?
▪ Phụ thuộc vào độ ưu tiên và chính sách lập lịch của
hệ thống
▪ Thay đổi độ ưu tiên của luồng sử dụng setPriority
và lấy ra độ ưu tiên hiện tại sử dụng getPriority
▪ MIN_PRIORITY (1), MAX_PRIORITY (10),
NORM_PRIORITY (5): 3 hằng số nguyên được định
nghĩa trong lớp Thread
▪ Daemon thread: luồng chạy ngầm

27
Tài liệu tham khảo
▪ Concurrent and Distributed Computing in Java, Vijay K. Garg,
University of Texas, John Wiley & Sons, 2005
▪ Tham khảo:
▪ Principles of Concurrent and Distributed Programming, M. Ben-Ari,
Second edition, 2006
▪ Foundations of Multithreaded, Parallel, and Distributed
Programming, Gregory R. Andrews, University of Arizona,
Addison-Wesley, 2000
▪ The SR Programming Language: Concurrency in Practice,
Benjamin/Cummings, 1993
▪ Xử lý song song và phân tán, Đoàn văn Ban, Nguyễn Mậu Hân, Nhà
xuất bản Khoa học và Kỹ thuật, 2009

28
LẬP
TRÌNH
ĐỒNG BÀI 2:
BÀI TOÁN LOẠI
THỜI TRỪ LẪN NHAU
& 1
PHÂN
TÁN Giảng viên: Lê Nguyễn Tuấn Thành
Email: thanhlnt@tlu.edu.vn
Mutex

NỘI DUNG
1. Bài toán loại trừ lẫn nhau trong những
hệ thống chia sẻ bộ nhớ
2. Giải pháp cho bài toán loại trừ lẫn
nhau

Bài giảng có sử dụng hình vẽ trong cuốn sách “Concurrent and Distributed Computing in Java, Vijay K. 2
Garg, University of Texas, John Wiley & Sons, 2005”
Thách thức trong các
chương trình đồng thời
▪ Đồng bộ sự thực thi của các luồng khác
nhau
▪ Cho phép các luồng giao tiếp với nhau
thông qua bộ nhớ chia sẻ

3
1. Phát biểu bài toán
Mất mát dữ liệu

Phần 1.
4
Bài toán loại
trừ lẫn nhau
Mutual Exclusion Problem - Mutex
“Lost update” Problem (1)
▪ Nguyên nhân: Race condition

▪ Xét tình huống:


▪ Có một biến chia sẻ x với giá trị ban đầu là 0
▪ Có hai luồng T0 và T1 đều tăng giá trị của x lên 1
▪ Liệu giá trị của x sau khi thực thi T0 và T1 sẽ là 2?

5
Luồng T0 Luồng T1
“Lost update”
Đọc giá trị x vào một thanh
Problem (2)
ghi (giá trị được đọc: 0)
Tăng thanh ghi (1)

Ghi giá trị trong thanh ghi


ngược lại x (x=1)
Đọc giá trị x vào một thanh
ghi (giá trị được đọc: 1)
Tăng thanh ghi (2)

Ghi giá trị trong thanh ghi


ngược lại x (x=2)

6
Luồng T0 Luồng T1
“Lost update”
Đọc giá trị x vào một thanh
Problem (3)
ghi (giá trị được đọc: 0)
Tăng thanh ghi (1)

Đọc giá trị x vào một thanh


ghi (giá trị được đọc: 0)
Tăng thanh ghi (1)

Ghi giá trị trong thanh ghi


ngược lại x (x=1)
Ghi giá trị trong thanh ghi
ngược lại x (x=1)

7
Làm sao để tránh
vấn đề mất mát dữ liệu?
▪ Câu lệnh x = x +1 phải được thực thi một
cách nguyên tử (atomically)
▪ Mở rộng ra, nếu một phần mã cần được thi
thực một cách nguyên tử thì phần mã đó
được gọi là: khu vực quan trọng (Critical
Region - CR) hay phần quan trọng (Critical
Section - CS)
▪ Cho ví dụ về CS ???

8
Bài toán loại trừ lẫn
nhau (Mutex)
▪ Là bài toán nhằm đảm bảo rằng khu vực quan
trọng (CR/CS) của một luồng phải được thực
thi theo một cách nguyên tử
▪ Là một trong những bài toán căn bản nhất trong
tính toán đồng thời
Giải pháp cho bài toán Mutex
- request CS
- release CS

9
Giao diện cho Bài toán
Mutex
▪ Định nghĩa giao diện Lock để đồng bộ việc
truy cập khu vực quan trọng (CR/CS) của các
luồng

lấy khoá

nhả khoá ra pid: định danh của luồng đang gọi phương th

10
giải pháp cho bài toán đa
luồng , bài toán loại trừ lẫn
nhau
=>> tránh mất mát dữ liệu
Thread-i Thread-j

requestCS(i) requestCS(j)

CSi CSj

releaseCS(i) releaseCS(j)

11
3 thuộc tính của 1 giải pháp tốt
2 cases:
- loại trừ lẫn nhau
- 2 luồng, T0, T1
- không lo khoá chết (deadlock)
- lớn hơn 2 luồng, T0, T1, T1+i
- không bị chết đói (starvation)

Phần 2.
12
Giải pháp cho
Bài toán Mutex
Busy-waiting solutions within a loop
Trường hợp
2 luồng
13
Thuật toán 1
▪ Sử dụng một biến chia sẻ giữa 2 luồng,
openDoor kiểu boolean được khởi tạo là true
▪ requestCS: luồng đợi cho đến khi biến
openDoor có giá trị true
▪ Khi giá trị của biến này là true, luồng có thể đi
vào CS, sau đó nó đặt lại giá trị của openDoor
thành false
▪ releaseCS: luồng đặt lại giá trị của biến
openDoor là true
14
biến chia sẻ

openDoor = true => thoát được ra vòng while


=>> sau đó chuyển trạng thái openDoor = false

15
▪ Cài đặt này không hoạt động đúng do
việc kiểm tra openDoor và việc đặt lại
giá trị biến này thành false không được
làm một cách nguyên tử
▪ Tưởng tượng rằng một luồng có thể
kiểm tra biến openDoor và vượt qua
Đánh câu lệnh while
▪ Tuy nhiên, trước khi luồng đó có thể
giá đặt biến openDoor thành false, luồng
thứ 2 bắt đầu thực hiện
thuật ▪ Luồng thứ 2 lúc này kiểm tra giá trị
của openDoor và cũng vượt qua câu
toán 1 lệnh while để đi vào CS !
▪ Cả hai luồng bây giờ đều có thể đặt
openDoor thành false và cùng đi vào
CS
▪ Do đó, cài đặt 1 vi phạm sự loại trừ
lẫn nhau !
16
Thuật toán 2:
Dẫn đến Deadlock
▪ Trong cài đặt 1, biến chia sẻ openDoor không
lưu lại luồng nào đã cập nhật nó thành false
▪ Cài đặt 2 giải quyết vấn đề này bằng cách sử
dụng 2 biến chia sẻ wantCS [0] và wantCS[1]

17
18
▪ Cài đặt này cũng không
làm việc đúng!
Đánh ▪ Cả hai luồng có thể CÙNG
giá LÚC đặt bit wantCS của
nó thành true và rơi vào
thuật vòng lặp đợi vô hạn do
đều chờ luồng kia đặt bit
toán 2 wantCS thành false!
▪ DEADLOCK !

19
Deadlock
▪ Thread 1: locks resource A, waits for resource B
▪ Thread 2: locks resource B, waits for resource A

20
Thuật toán 3:
Luân phiên chặt chẽ
▪ Cài đặt 3 cũng khắc phục được vấn đề lưu vết
luồng đã thực hiện sự thay đổi trên biến chia
sẻ, xảy ra ở cài đặt 1
▪ Cài đặt này được dựa trên việc kiểm tra giá
trị của biến chia sẻ turn
▪ Một luồng sẽ đợi đến lượt nó để đi vào CS.
Khi thoát ra khỏi CS, nó đặt lại giá trị biến
turn thành 1-i

21
22
▪ Cài đặt 3 bảo đảm sự loại trừ lẫn
nhau !
▪ Cài đặt này cũng đảm bảo rằng
nếu cả hai luồng đang cố gắng để
đi vào CS, thì một trong số hai
Đánh luồng sẽ đi vào CS thành công
▪ Tuy nhiên, cài đặt này phát sinh
giá một vấn đề khác
thuật ▪ Cả 2 luồng phải luân phiên nhau để đi
vào CS !

toán 3 ▪ Do đó, sau khi luồng T0 thoát khỏi CS,


T0 không thể đi vào CS nữa cho đến khi
luồng T1 đi vào CS và thay đổi lại giá
trị của biến turn !
▪ Nếu T1 không quan tâm tới việc đi vào
CS, thì T0 sẽ bị tắc lại vô hạn do phải
đợi P1 !
23
Thuật toán Peterson (1)
▪Kết hợp 2 cách tiếp cận trước để giải
quyết bài toán mutex trong một hệ
thống có 2 luồng hoạt động đồng thời
▪Trong thuật toán này, chúng ta lưu giữ
2 cờ/bit, wantCS[0] và wantCS[1], như
cài đặt 2, và một biến turn như trong
cài đặt 3

24
25
1. Loại trừ lẫn nhau (mutual
exclusion)
▪ Cả hai luồng không thể ở
trong CS tại cùng một thời
Đánh điểm
2. Tiến độ (progress)
giá ▪ Nếu một hoặc hai luồng đang

thuật cố gắng đi vào CS và không có


luồng nào bên trong CS, thì ít
toán nhất một luồng sẽ đi vào CS
thành công
Peterson 3. Không chết đói
(starvation-freedom)
▪ Nếu một luồng đang cố gắng
đi vào CS, thì cuối cùng nó
phải được đi vào CS 26
Trường hợp
N luồng (N>2)
27
Thuật toán Bakery của
Lamport (1)
▪ Ý tưởng tương tự như
cách các tiệm bánh
phục vụ khách hàng
▪ Mỗi khách hàng khi đến
tiệm bánh được phát
cho một số hiệu duy
nhất
▪ Tại một thời điểm,
tiệm bánh sẽ phục vụ
khách hàng đang giữ số
nhỏ nhất hiện tại
28
Thuật toán Bakery của
Lamport (2)
▪ Một luồng Ti phải đi qua 2 bước chính trước khi có
thể đi vào CS
1. Bước 1: được gọi là doorway
▪ Ti được yêu cầu chọn một số
▪ Ti
đọc số của tất cả những luồng khác và chọn ra một số
lớn hơn số lớn nhất mà nó đọc được
2. Bước 2: kiểm tra 2 điều kiện để đi vào CS
▪ Với mỗi luồng Tj khác, Ti kiểm tra liệu Tj có đang ở
trong doorway không. Nếu Tj đang ở trong doorway, thì
Ti phải đợi cho Tj ra khỏi doorway
▪ Ti phải đợi cho number[j] bằng 0 hoặc (number[i], i) <
(number[j], j) 29
Thuật toán Bakery
của Lamport

Tại sao phải kiểm tra:


number[j] == number[i]
&& j < i ? 30
▪ Thuật toán thỏa mãn sự
loại trừ lẫn nhau
Đánh ▪ Thuậttoán cũng thỏa
mãn điều kiện không chết
giá đói
thuật ▪ Do bất kỳ luồng nào đang
đợi để đi vào CS thì cuối
toán cùng nó cũng sẽ có giữ số
nhỏ nhất khác 0 tại một
Bakery thời điểm nào đó
▪ Khi đó, luồng này sẽ đi vào
CS thành công !

31
Đánh ▪ Thuật toán luôn đòi hỏi
giá thời gian O(N) cho mỗi
luồng khi muốn lấy được
thuật khóa (lock) mặc dù có thể
không có tranh chấp
toán ▪ Thuật toán đòi hỏi mỗi
Bakery: luồng sử dụng dấu thời
gian (timestamps), i.e. số
Nhược id, với giá trị không bị
giới hạn
điểm
32
Lớp ReentrantLock
myLock.lock(); // Một đối tượng ReentrantLock
try
{
<khu vực quan trọng (critical section)>
}
finally
{
myLock.unlock(); // Đảm bảo lock được khoá lại ngay cả
khi một ngoại lệ được ném ra
} 33
Tài liệu tham khảo
▪ Concurrent and Distributed Computing in Java, Vijay K. Garg,
University of Texas, John Wiley & Sons, 2005
▪ Tham khảo:
▪ Principles of Concurrent and Distributed Programming, M. Ben-Ari,
Second edition, 2006
▪ Foundations of Multithreaded, Parallel, and Distributed
Programming, Gregory R. Andrews, University of Arizona,
Addison-Wesley, 2000
▪ The SR Programming Language: Concurrency in Practice,
Benjamin/Cummings, 1993
▪ Xử lý song song và phân tán, Đoàn văn Ban, Nguyễn Mậu Hân, Nhà
xuất bản Khoa học và Kỹ thuật, 2009

34
LẬP
TRÌNH
BÀI 3:
ĐỒNG NHỮNG CƠ SỞ
THỜI ĐỒNG BỘ HOÁ
& 1
PHÂN
TÁN Giảng viên: Lê Nguyễn Tuấn Thành
Email: thanhlnt@tlu.edu.vn
Synchonization primitives

2
NỘI DUNG
1. Busy-waiting problem
2. Semaphore
3. Monitor

Bài giảng có sử dụng hình vẽ trong cuốn sách “Concurrent and Distributed Computing in Java, Vijay K.
Garg, University of Texas, John Wiley & Sons, 2005” 3
Busy-waiting problem
▪ Những giải pháp ở bài trước gặp một vấn đề
chung: bận chờ (busy-wait) khi sử dụng vòng
lặp while
▪ Khi một luồng không thể đi vào CS, nó sẽ liên lục
kiểm tra điều kiện ở while
▪ Điều này khiến luồng không thể thực hiện các công
việc khác => gây lãng phí chu trình CPU
▪ Thay vì phải kiểm tra liên tục điều kiện vào CS, nếu
một luồng chỉ kiểm tra khi điều kiện này trở thành
true thì sẽ không lãng phí chu trình CPU

4
Synchnization primitives
▪ Những cơ sở đồng bộ hóa giúp giải quyết vấn
đề bận chờ
▪ Hai cấu trúc đồng bộ phổ biến:
▪ Semaphore do Dijkstra đề xuất, năm 1968
▪ Monitor được phát minh bởi P. B. Hansen và C. A.
R. Hoare, năm 1972

5
6
Phần 2.
Semaphore
Semaphores were invented by Edsger Dijkstra, 1968
Source: https://www.e-reading.club/chapter.php/102147/92/Li%2C_Yao_-_Real-Time_Concepts_for_Embedded_Systems.html

7
8
Semaphore nhị phân (1)
P():
▪ Một biến value if (value == false) {
kiểu boolean Thêm bản thân luồng Được thực
vào hàng đợi và khóa lại; thi nguyên
▪ Một hàng đợi các } tử
tiến trình bị khóa value = false;

▪ Hai thao tác V():


nguyên tử: P() và value = true;
V() if (hàng đợi không rỗng) {
Đánh thức một luồng
Được thực
bất kỳ trong hàng đợi; thi nguyên
} tử

9
10
Semaphore nhị phân (2)
Ví dụ cài đặt

Phương thức myWait() sẽ khóa luồng hiện tại và


chèn nó vào trong hàng đợi các luồng bị khóa 11
Semaphore nhị phân
cho Bài toán Mutex

12
Semaphore đếm (1)

13
Semaphore đếm (2)
Ví dụ cài đặt

14
Tìm hiểu: java.util.concurrent.Semaphore
Sử dụng Semaphore
cho một số bài toán
đồng bộ
15
Bài toán 1: Nhà sản xuất
& Người tiêu thụ (1)
▪ Hai luồng:
1. Luồng 1: Producer
2. Luồng 2: Consumer

▪ Bộ đệm chia sẻ là một


mảng vòng tròn có kích
thước size, gồm:
▪ Hai con trỏ inBuf và outBuf
▪ Biến count để lưu tổng số
phần tử hiện tại

16
Bài toán 1: Nhà sản xuất
& Người tiêu thụ (2)
▪ Ngoài
việc đảm bảo loại trừ lẫn nhau, bài toán này có
thêm 2 rằng buộc đồng bộ có điều kiện:
1. Luồng sản xuất chỉ thực hiện thêm 1 phần tử vào cuối bộ
đệm nếu: bộ đệm không đầy
2. Luồng tiêu thụ chỉ thực hiện lấy 1 phần tử khỏi của bộ
đệm nếu: bộ đệm không rỗng
▪ Bộ đệm sẽ đầy nếu producer thêm phần tử với tốc độ
lớn hơn tốc độ lấy phần tử của consumer
▪ Bộ đệm sẽ rỗng nếu … ?

17
Lớp BoundedBuffer
Sử dụng mutex Semaphore

18
19
Bài toán 2: Người đọc &
Người ghi
▪ Phối hợp truy cập tới một cơ sở dữ liệu chia
sẻ giữa nhiều người đọc và nhiều người ghi
▪ Các rằng buộc đồng bộ:
1. Rằng buộc đọc-ghi: Một người đọc và một người
ghi không được truy cập đồng thời vào CSDL chia
sẻ
2. Rằng buộc ghi-ghi: Hai người ghi không được truy
cập đồng thời vào CSDL chia sẻ
3. Nhiều người đọc có thể đồng thời truy cập CSDL
chia sẻ
20
Giải pháp cho
Bài toán Người đọc – Người ghi
Sử dụng Semaphore

21
Readeri Readerj Writerk Writerl

startRead() startRead() startWrite() startWrite()

Quá trình Quá trình Quá trình Quá trình


đọc dữ liệu đọc dữ liệu ghi dữ liệu ghi dữ liệu

endRead() endRead() endWrite() endWrite()

Starvation of a writer ?
22
Bài toán 3: Bữa tối của
Triết gia (1)

23
Bài toán 3: Bữa tối của
Triết gia (2)
Triết gia thứ i
▪ N triết gia:
while (true) {
▪ Nghĩ, Đói & Ăn
// suy nghĩ trong một thời
▪ N cái nĩa (fork) gian, bắt đầu đói
▪ N semaphore fork[i].P();
▪ fork [1..N] fork[(i+1) % 5].P();
▪ Một semapore cho một
//ăn; (vùng quan trọng - CS)
cái nĩa
fork[i].V();
fork[(i+1) % 5].V();
} 24
25
26
Bài toán 3: Tình huống
Deadlock
Triết gia 1 Triết gia 2 Triết gia 3 Triết gia 4 Triết gia 5
fork[1].P(); fork[2].P(); fork[3].P(); fork[4].P(); fork[5].P();
fork[2].P(); fork[3].P(); fork[4].P(); fork[5].P(); fork[1].P();

Có khả năng mọi luồng đều bị tắc nghẽn:


Deadlock
fork[1
]
fork[5 fork[2
] ]

fork[4 fork[3
27
] ]
Bài toán 3: Giải pháp
tránh Deadlock
Triết gia 1 Triết gia 2 Triết gia 3 Triết gia 4 Triết gia 5
fork[1].P(); fork[2].P(); fork[3].P(); fork[4].P(); fork[1].P();
fork[2].P(); fork[3].P(); fork[4].P(); fork[5].P(); fork[5].P();

Tránh chu trình


fork[1
]
fork[5 fork[2
] ]

fork[4 fork[3
] ] 28
29
Phần 2.
Monitor
Invented by P. B. Hansen and C. A. R. Hoare, 1972
Monitor (1)
▪Semaphore là một công cụ mạnh cho bài
toán đồng bộ luồng ở mức thấp, nhưng
không thật sự hướng đối tượng
▪Monitor ở mức cao hơn, hướng đối
tượng và dễ sử dụng hơn
▪ Có thể sử dụng Semaphore để cài đặt
Monitor và ngược lại

30
31
Monitor (2)
▪ Monitor có thể được xem như một lớp
trong lập trình đồng thời gồm: dữ liệu và
các thao tác trên dữ liệu đó
▪ Monitor hỗ trợ khái niệm phương thức
entry để đảm bảo loại trừ lẫn nhau
▪ Tại một thời điểm, chỉ có nhiều nhất 1
luồng có thể thực thi trong một phương
thức entry
▪ Monitor đi kèm với một hàng đợi chứa
những luồng đang đợi để vào monitor
32
Monitor (3)
▪ Monitor hỗ trợ khái niệm biến điều kiện cho
trường hợp yêu cầu sự đồng bộ có điều kiện
▪ Một luồng phải đợi một điều kiện nào đó trở
thành đúng
▪ Mỗi biến điều kiện x định nghĩa 2 thao tác:
▪ wait: khoá luồng gọi và đưa vào hàng đợi của x
▪ notify hoặc signal: loại một luồng khỏi hàng
đợi của x và và chèn nó vào hàng đợi
sẵn-sàng-thực-thi

33
Ngữ nghĩa
của Monitor (1)
▪ Trong Java, sử dụng từ khoá synchronized để
quy định một đối tượng là một Monitor

synchronized enterMonitor():
(object) { cho phép đi vào monitor nếu
không có luồng nào trong đó;
Tương tự ngược lại, đi vào hàng đợi
….
một khu các luồng bị khoá;
….
vực quan
….
trọng (CS) exitMonitor():
thoát khỏi monitor và
} đánh thức cho luồng khác
đang bị khoá
34
35
Ngữ nghĩa
của Monitor (2)
Các phương thức sử dụng bên trong Monitor
Dừng thực thi luồng hiện
tại, thả khoá, đặt luồng này
synchronized (object) vào hàng đợi của object và
{ chờ cho đến khi luồng khác
…. đánh thức
object.wait();
…. Nếu hàng đợi không rỗng,
object.notify(); chọn một luồng tùy ý trong
…. hàng đợi và đánh thức nó
object.notifyAll(); Nếu hàng đợi không rỗng,
…. đánh thức tất cả luồng
} trong hàng đợi
36
Hai kiểu Monitor
Luồng 0 Luồng 1

synchronized (object) {
….
object.wait();
synchronized (object) {
….
object.notify();
Luồng nào nên tiếp tục thực hiện vào thời điểm này?
…. ….
} }

Do chỉ có một luồng có thể được ở bên trong Monitor tại một thời điểm.
37
Hai khả năng …
Hoare-style Monitor (1)
Blocking condition variables
Luồng 0 Luồng 1
synchronized (object) {
….
object.wait();
synchronized (object) {
….
object.notify();
….
}
….
}
Luồng 0 sẽ đi vào monitor ngay lập tức 38
sau khi luồng 1 gọi hàm notify()
Hoare-style Monitor (2)
Blocking condition variables
Luồng 0 Luồng 1
synchronized (object) {
if (x != 1)
object.wait();
synchronized (object) {
if (x==1)
object.notify();
assert(x==1); // x phải bằng
1
x++;
}
// x có thể không còn bằng 1 nữa ở
đây
}
Luồng 0 không phải lo lắng về sự thay đổi trạng 39

thái của môi trường, biến điều kiện, so với ban


Mesa-style Monitor (1)
Nonblocking condition variables
Luồng 0 Luồng 1
synchronized (object) {
….
object.wait();
synchronized (object) {
….
object.notify();
….
}
….
}

Luồng 1 tiếp tục thực hiện sau khi gọi hàm notify() 40
Sau khi luồng 1 ra khỏi monitor, luồng 0 có thể đi vào monitor
Mesa-style Monitor (2)
Nonblocking condition variables
Luồng 0 Luồng 1
synchronized (object) {
if (x != 1)
object.wait();
synchronized (object) {
if (x==1)
object.notify();
assert(x == 1); //phải bằng 1
}

// x có thể khác 1 ở đây


}

Trạng thái của môi trường khi luồng 0 được phép 41


đi vào monitor có thể đã thay đổi so với ban đầu
Mesa-style Monitor (3)
Nonblocking condition variables
Luồng 0 Luồng 1
synchronized (object) {
while (x != 1)
object.wait();
synchronized (object) {
x=1;
object.notify();
assert(x == 1); //phải bằng 1
}

assert(x == 1); //phải bằng 1


}
Luồng 0 phải sử dụng while để đảm bảo trạng thái của môi trường phù hợp 42
(Lý do: khi luồng 0 được phép đi vào monitor, thức dậy, để tiếp tục chạy, nó vẫn đang ở trong vòng
Hai cấu trúc sử dụng
Monitor trong Java

public synchronized void public void myMethod () {


myMethod () { synchronized (this) {
…. ….
….
…. = ….
….
}
} }

Các phương thức tĩnh cũng có thể được đồng bộ hóa


43
Sử dụng Monitor
cho một số bài
toán đồng bộ
44
Bài toán 1: Nhà sản xuất
& Người tiêu thụ (1)
object sharedBuffer;

void produce() { // or deposit void consume() { // or fetch


synchronized (sharedBuffer) { synchronized (sharedBuffer) {
while (sharedBuffer đầy) while (bộ đệm rỗng)
sharedBuffer.wait(); sharedBuffer.wait();
Thêm 1 phần tử vào bộ đệm; Lấy 1 phần tử khỏi bộ đệm;
if (bộ đệm không rỗng) if (bộ đệm không đầy)
sharedBuffer.notify(); sharedBuffer.notify();
} }
} }

45
Lớp Bounded buffer
monitor

46
Bài toán 2: Người đọc –
Người ghi
int numReader, numWriter; Object object;
void writeDB() { void readDB() {
synchronized (object) { synchronized (object) {
while (numReader > 0 || while (numWriter > 0)
numWriter > 0) object.wait();
object.wait(); numReader++;
numWriter = 1; }
} // đọc dữ liệu từ DB (không
// ghi dữ liệu vào DB (không cần phải ở trong monitor);
cần phải ở trong monitor); synchronized (object) {
synchronized (object) { numReader--;
numWriter = 0; object.notify();
object.notifyAll(); }
} }
Luồng được đánh thức phải là một
} 47
người ghi hay người đọc? Chứng minh
public synchronized void acquire(int i) {
Bài toán 3: Bữa tối của         state[i] = hungry;
        checkStartEating(i);
        while (state[i] != eating)
            Util.myWait(this);
}
Triết gia

public synchronized void release(int i) {


        state[i] = thinking;
        checkStartEating(left(i));
        checkStartEating(right(i));
}
void checkStartEating(int i) {
        if ( (state[left(i)] != eating) && (state[right(i)] !=
eating) && (state[i] == hungry) ) {
            state[i] = eating;
            notifyAll();
    }
} 48
Tài liệu tham khảo
▪ Concurrent and Distributed Computing in Java, Vijay K. Garg,
University of Texas, John Wiley & Sons, 2005
▪ Tham khảo:
▪ Principles of Concurrent and Distributed Programming, M. Ben-Ari,
Second edition, 2006
▪ Foundations of Multithreaded, Parallel, and Distributed
Programming, Gregory R. Andrews, University of Arizona,
Addison-Wesley, 2000
▪ The SR Programming Language: Concurrency in Practice,
Benjamin/Cummings, 1993
▪ Xử lý song song và phân tán, Đoàn văn Ban, Nguyễn Mậu Hân, Nhà
xuất bản Khoa học và Kỹ thuật, 2009

49
LẬP
TRÌNH
BÀI 4:
ĐỒNG CÁC KỸ THUẬT
THỜI LẬP TRÌNH PHÂN TÁN
& 1
PHÂN
TÁN Giảng viên: Lê Nguyễn Tuấn Thành
Email: thanhlnt@tlu.edu.vn
Nhắc lại:
Hệ thống phân tán
▪ Bao gồm nhiều máy tính
kết nối với nhau
▪ Không có các biến chia sẻ
▪ Trao đổi thông qua các
kênh truyền thông để gửi
và nhận thông điệp
▪ Thường sử dung lý thuyết
đồ thị để minh hoạ những
hệ thống phân tán

2
NỘI DUNG
1. Các mô hình truyền thông điệp
2. Giao thức truyền thông điệp: UDP, TCP
3. Lập trình truyền thông điệp:
▪ Ở mức thấp
▪ SOCKET
▪ MPI (Message Passing Interface)
▪ Ở mức cao:
▪ RMI (Remote Method Invocations)
▪ MOM (Message-Oriented Middleware)

Bài giảng có sử dụng hình vẽ trong cuốn sách “Concurrent and Distributed Computing in Java, Vijay K. 3
Garg, University of Texas, John Wiley & Sons, 2005”
Phần 1.
4
Các mô hình
truyền thông
điệp
Các mô hình
truyền thông điệp
Truyền thông điệp là phương thức
giao tiếp giữa các tiến trình thông qua
việc gửi thông điệp

5
Mô hình
Point-to-Point

6
Mô hình
Publish&Subscribe

7
Phần 2.
8
Giao thức truyền
thông điệp
10
UDP vs. TCP
UDP TCP
(Universal Datagram Protocol) (Transmission Control Protocol)

▪ Không kết nối ▪ Hướng kết nối


▪ Không truyền lại ▪ Tincậy (nhận đủ,
▪ Không bảo đảm nhận
không trùng lặp)
được theo thứ tự đã ▪ Đảm bảo thứ tự nhận
gửi được của các gói tin
▪ Có thể bị mất, bị ▪ Không bị mất gói tin
trùng lặp

11
Phần 3.
12
Lập trình
truyền thông
điệp trên Java
Lớp InetAddress (1)
▪ Bất kỳ máy tính kết nối với Internet (i.e.,
host) có thể được xác định duy nhất bằng
một địa chỉ internet (i.e., địa chỉ IP)
▪ Do địa chỉ số này khó nhớ, mỗi host cũng có
thêm một tên (i.e., hostname) đi kèm
▪ Máy chủ phân giải hệ thống tên miền (i.e.,
DNS) giúp cung cấp ánh xạ từ tên máy đến địa
chỉ của nó.

13
Lớp InetAddress (2)

14
Lập trình
15
Socket trên
Java
3.1.
Khái niệm Socket
16
Socket
▪ Socket là một điểm cuối của liên kết truyền thông hai
chiều giữa hai chương trình đang chạy trên mạng.
▪ Một Socket được liên kết với một số hiệu cổng để có
thể xác định ứng dụng địch mà dữ liệu sẽ được gửi
đến.
▪ Do đó, Socket là sự kết hợp của địa chỉ IP và số hiệu
cổng
▪ Ví dụ: 206.62.226.25,p21

▪ Hai socket sẽ xác định một kết nối: socket pair

17
3.2.
Lập trình Socket dựa
trên UDP
18
Lớp DatagramSocket (1)
▪ Sử dụng giao thức UDP để gửi và nhận thông điệp
▪ Ưu điểm: cho phép truyển dữ liệu nhanh
▪ Một datagram socket là điểm gửi hoặc nhận cho một
dịch vụ vận chuyển gói tin không kết nối
▪ Mỗi gói tin gửi hoặc nhận trên datagram socket
được định địa chỉ và định tuyến một cách riêng biệt

19
20
Source: https://slideplayer.com/slide/4969080/
Lớp DatagramSocket (2)
▪ public void close()

▪ public int getLocalPort()

▪ public InetAddress getLocalAddress()

▪ public void receive(DatagramPacket p)


▪ Nhận một gói datagram từ socket
▪ Khi trả về từ phương thức này, bộ đệm của p được điền đầy
dữ liệu nhận được
▪ Phương thức chặn cho đến khi nhận được một datagram

▪ public void send(DatagramPacket p)


▪ Gửi một gói datagram từ socket
▪ DatagramPacket bao gồm các thông tin về dữ liệu, chiều dài
của dữ liệu, địa chỉ IP & cổng của máy đích
21
Chương trình mẫu: Echo
server
▪ Hệ thống gồm 2 tiến trình cho:
▪ Server
▪ Client
▪ Client đọc dữ liệu đầu vào từ người dùng và gửi
nó đến server
▪ Server nhận được gói tin datagram và sau đó gửi
trả lại chính dữ liệu đó cho client
▪ Client đọc một dòng đầu vào bàn phím
▪ Sau đó, client tạo một gói tin datagram và gửi tới
server
▪ Khi nhận được phản hồi từ server, client sẽ hiển
thị thông báo nhận được
22
3.3.
Lập trình Socket dựa
trên TCP
23
Lập trình Socket dựa
trên TCP
▪ Dựa trên khái niệm về dòng tin (stream)
▪ Một kết nối TCP được thiết lập giữa tiến
trình gửi và tiến trình nhận
▪ Cho phép phục hồi lỗi tốt hơn và đảm bảo
thứ tự phân phối các gói dữ liệu.
▪ Trong một stream, các gói được nhận theo
đúng thứ tự như khi chúng được gửi đi.
▪ Sử dụng lớp Socket cho phía client và
ServerSocket cho phía server
24
Source: https://www.safaribooksonline.com/library/view/distributed-computing-in/9781787126992/02dd04be-0dbb-4732-8bc5-1961644e8875.xhtml

25
Lớp Socket phía client
▪ public Socket (String host, int port)
▪ Tạo một stream socket và kết nối nó tới một cổng trên host.
▪ Có thể ném ra ngoại lệ UnknownHostException và IOException.

▪ public Socket(InetAddress address, int port)


▪ Một số phương thức của lớp Socket:
▪ public InetAddress getInetAddress()
▪ public InetAddress getLocalAddress()
▪ public int getport()
▪ public Inputstream getInputStream()
▪ public Outputstream getOutputStream()
▪ public synchronized void close()

26
Lớp ServerSocket
▪ public ServerSocket(int port)
▪ Một số phương thức của lớp ServerSocket:
▪ public InetAddress getInetAddress()
▪ public int getLocalPort()
▪ public Socket accept()
▪ public void close()

27
Chương trình mẫu:
NameServer
▪ Một bảng phân giải tên <name: hostName,
portNumber>
▪ Giúp một ánh xạ từ tên chương trình tới địa chỉ
và cổng mà tại đó chương trình đó đang chạy
▪ Giả định rằng kích thước tối đa của bảng
phân giải tên là 100
▪ Hai phương thức:
▪ insert
▪ search

28
29 3.4.
Lập trình RMI

Remote Method Invocations


Khái niệm RMI (1)
▪ Ý tưởng chính: cho phép một luồng T1 chạy trên
máy ảo VM1 có thể thực hiện lời gọi đến phương
thức M2 của một đối tượng O2 chạy trên máy ảo
VM2 khác giống như gọi phương thức M1 của đối
tượng O1 nằm trên cùng một máy ảo với T1
▪ Đối tượng O2 nằm ở máy ảo VM2 khác với luồng T1
được gọi là đối tượng ở xa
▪ Luồng tạo lời gọi (T1) được gọi là client
▪ Luồng phục vụ yêu cầu (T2) được gọi là server

▪ Trong RMI, client có thể không cần biết về vị trí


của đối tượng ở xa !

30
Khái niệm RMI (2)
▪ Các đối số của phương thức M2, khi đối tượng
ở xa O2, được gửi thông qua thông điệp
▪ Tương tự, giá trị trả về của phương thức M2
được truyền đến nơi gọi thông qua thông điệp
▪ Tất cả các thông điệp này được ẩn đi đối với
lập trình viên
▪ Do đó RMI có thể được xem như là một cấu trúc lập
trình bậc cao hơn so với gửi hoặc nhận thông điệp
bằng socket

31
Cài đặt RMI
▪ Với mỗi đối tượng ở xa sẽ phát sinh thêm:
▪ một đối tượng liên kết ở phía client và
▪ một đối tượng ở phía server

▪ Lời gọi tới đối tượng ở xa ở phía client được quản lý


bằng cách sử dụng đối tượng đại diện cho client,
được gọi là stub
▪ Stub sẽ đóng gói tên phương thức và các đối số trong một
thông điệp và truyền tới phía server
▪ Thông điệp này được nhận ở phía server bởi đối
tượng đại diện, gọi là skeleton
▪ Skeleton có trách nhiệm tiếp nhận thông điệp, lấy ra các đối
số, và cuối cùng gọi phương thức thích hợp ở phía server 32
Source: http://www.rizzimichele.it/remote-methode-invocation/

33
Cơ chế vận hành theo RMI
(1)
▪ Bước 1: Server tạo ra đối
tượng cho phép được gọi từ
xa cùng với các Stub và
Skeleton tương ứng của đối
tượng đó
▪ Bước 2: Server sử dụng lớp
Naming để đăng ký tên cho đối
tượng từ xa (1)
▪ Bước 3: Naming đăng ký Stub
của đối tượng từ xa với
RMIRegistry (2)
▪ Bước 4: RMIRegistry sẵn sàng
cung cấp tham chiếu đến đối
tượng từ xa khi có yêu cầu (3)34
Cơ chế vận hành theo RMI
(2)
▪ Bước 5: Client yêu cầu
Naming định vị đối tượng ở
xa qua tên đã được đăng ký
(phương thức lookup) với
RMIRegistry (4)
▪ Bước 6: Naming tải Stub của
đối tượng xa từ RMIRegistry
về Client (5)
▪ Bước 7: Cài đặt đối tượng
Stub và trả về tham chiếu đối
tượng ở xa cho Client (6)
▪ Bước 8: Client thực thi một
lời gọi các phương thức ở xa
thông qua đối tượng Stub (7)
35
Con đường kích hoạt một
phương thức ở xa

36
Khai báo đối tượng ở xa
▪ Đối tượng ở xa được định nghĩa sử dụng một
giao diện ở xa, được mở rộng từ lớp
java.rmi.Remote

37
Cài đặt RMI Server (1)
1. Để cài đặt rmi server, đầu tiên chúng ta biên dịch
file chứa lớp từ xa (vd. NameServiceImpl.java)
2. Sau đó, chúng ta cần tạo đối tượng stub liên kết
với client và đối tượng skeleton liên kết với server
3. Tiếp theo đăng ký đối tượng ở xa với RMIRegistry
bằng lệnh rmiregistry
Các bước:
> javac NameServiceImpl.java
> rmic NameServiceImpl
> rmiregistry &
38
Cài đặt RMI Server (2)
▪ Vấn đề bảo mật !
▪ Tệp tin chính sách bảo mật (file security
policy)
▪ Ví dụ một file security policy:

39
Cài đặt RMI Server (3)
▪ Bây giờ có thể khởi động RMI Server:
> java -Djava.security.policy=policy NameServiceImpl

40
Cài đặt RMI Client (1)
▪ Lớp java.rmi.Naming cung cấp những phương
thức để lấy được tham chiếu của đối tượng ở
xa
▪ Một cách để lấy về tham chiếu đến đối
tượng ở xa là dựa trên cú pháp URL
▪ URL cho một đối tượng ở xa được xác định
bằng cú pháp rmi://host:port/name
▪ host là tên của RMIRegistry
▪ port là số cổng của RMIRegistry,
▪ name là tên của đối tượng ở xa.
41
Phương thức chính của
lớp Naming

42
Cài đặt RMI Client (2)

43
3.5.
44
Message-Oriented
Middleware
Tài liệu Tham khảo
▪ Concurrent and Distributed Computing in Java,
Vijay K. Garg, University of Texas, John Wiley & Sons,
2005
▪ Tham khảo:
▪ Principles of Concurrent and Distributed Programming, M.
Ben-Ari, Second edition, 2006
▪ Foundations of Multithreaded, Parallel, and Distributed
Programming, Gregory R. Andrews, University of Arizona,
Addison-Wesley, 2000
▪ The SR Programming Language: Concurrency in Practice,
Benjamin/Cummings, 1993
▪ Xử lý song song và phân tán, Đoàn văn Ban, Nguyễn Mậu Hân,
Nhà xuất bản Khoa học và Kỹ thuật, 2009

47
LẬP
TRÌNH BÀI 5:
ĐỒNG MÔ HÌNH VÀ
ĐỒNG HỒ
THỜI TRONG TÍNH
& TOÁN PHÂN TÁN
1
PHÂN
TÁN Giảng viên: Lê Nguyễn Tuấn Thành
Email: thanhlnt@tlu.edu.vn
Giới thiệu
▪ Khi một chương trình phân tán thực thi, một tập các
sự kiện được tạo ra
▪ Tập sự kiện này và Mối quan hệ thứ tự, mối quan
hệ trước sau, trên tập sự kiện đó sẽ quy định cách
hành xử của một hệ thống phân tán
▪ Mỗi máy tính trong hệ thống phân tán có đồng hồ
riêng

2
Source: https://cloud.addictivetips.com/wp-content/uploads/2012/07/Clock-grid-Advanced-World-Clock.png

3
Trong hệ thống phân
tán, các sự kiện xảy ra
khi nào và thứ tự thực
hiện của chúng là gì?

4
NỘI DUNG
▪Mô hình đã-xảy-ra-trước
▪Cơ chế đồng hồ để lưu vết thứ tự trên
tập các sự kiện đã xảy ra
▪Đồng hồ logic
▪Đồng hồ vector
▪Đồng hồ phụ-thuộc-trực tiếp
▪Đồng hồ ma trận

Bài giảng có sử dụng hình vẽ trong cuốn sách “Concurrent and Distributed Computing in Java, Vijay K. Garg, 5
University of Texas, John Wiley & Sons, 2005”
Đặc điểm của
Hệ thống phân tán (1)
1. Thường thiếu một đồng hồ chia sẻ
▪ Không thể đồng bộ đồng hồ của các BXL
khác nhau do độ trễ của việc truyền thông
điệp
▪ Hiếm khi sử dụng đồng hồ vật lý để đồng bộ
▪ Sử dụng khái niệm nhân quả thay cho thời
gian vật lý để đồng bộ các sự kiện

6
Đặc điểm của
Hệ thống phân tán (2)
2. Thiếu bộ nhớ chia sẻ
▪ Không có một BXL nào biết được trạng thái
toàn cục của hệ thống phân tán
▪ Khó khăn trong việc quan sát một thuộc tính
bất kỳ của hệ thống

7
Đặc điểm của
Hệ thống phân tán (3)
3. Khó phát hiện các nguyên nhân sai lệch
▪ Trong một hệ thống phân tán bất đồng bộ,
không thể phân biệt giữa một BXL chậm và
một BXL bị lỗi
▪ Khó khăn trong việc phát triển các thuật
toán cho các bài toán đồng thuận, bài toán
bầu cử,… trong hệ thống phân tán

8
Hệ thống phân tán:
đồng bộ và bất đồng bộ
HT phân tán bất đồng
HT phân tán đồng bộ
bộ
▪ Tốc độ và thời gian ▪ Tốc độ và thời gian
thực thi bị giới hạn thực thi không bị giới
hạn
▪ Quá trình truyền
▪ Quá trình truyền
thông điệp có độ trễ
thông điệp có độ trễ
bị giới hạn không bị giới hạn
▪ Thứ tự phân phối ▪ Thông điệp truyền đi
thông điệp được đảm theo thứ tự ngẫu
bảo (e.g. FIFO) nhiên
9
Giả định cho hệ
thống phân tán
được nghiên cứu
10
Hệ thống phân tán được
nghiên cứu (1)
▪ Hệ thống phân tán bất đồng bộ
▪ Một chương trình phân tán sẽ bao gồm:
▪ Tập N tiến trình được biểu thị bằng {P1,P2,...,PN}
▪ Tập các kênh đơn hướng, mỗi kênh kết nối hai tiến
trình
▪ Topology có thể được xem như là một đồ thị
có hướng

11
Hệ thống phân tán được
nghiên cứu (2)
▪ Một kênh truyền được giả định có bộ đệm vô
hạn và không có lỗi trong quá trình truyền
thông điệp trên kênh đó
▪ Không yêu cầu về thứ tự của các thông điệp
▪ Thông điệp gửi trên kênh có thể có độ trễ tùy ý
nhưng không thể vô hạn
▪ Trạng thái của kênh tại một điểm được định
nghĩa là chuỗi các thông điệp được gửi đi
trên theo kênh đó

12
Hệ thống phân tán được
nghiên cứu (3)
▪ Một tiến trình trong hệ thống phân tán được
định nghĩa gồm:
▪ Tập các trạng thái (e.g. chuỗi các thông điệp gửi)
▪ Tập các sự kiện (e.g. sự kiện nhận, gửi thông
điệp, …)
▪ Điều kiện ban đầu (e.g. tập con của tập trạng
thái)
▪ Khi một sự kiện xảy ra có thể thay đổi trạng
thái của tiến trình và trạng thái của tối đa một
kênh trên tiến trình đó
13
Sơ đồ chuyển trạng thái
của hai tiến trình

14
Mô hình trong
15
tính toán phân
tán
Happened-before Model
Mô hình
đã-xảy-ra-trước (1)
▪ Trên từng bộ xử lý, có thể quan sát được thứ tự
toàn bộ của các sự kiện xảy ra trên bộ xử lý đó
▪ Nhưng một bộ xử lý chỉ quan sát được một thứ
tự bộ phận, hay từng phần, của các sự kiện xảy
ra trên các bộ xử lý khác

16
Mô hình
đã-xảy-ra-trước (2)
▪ Lamport lập luận rằng trong một hệ thống
phân tán thực sự thì chỉ có một trật tự từng
phần, được gọi là mối quan hệ
đã-xảy-ra-trước, có thể được xác định giữa
các sự kiện
▪ Làm sao để xác định thứ tự toàn cục của tập
các sự kiện của các tiến trình khác nhau trong
hệ thống phân tán?

17
Mô hình
đã-xảy-ra-trước (3)
Định nghĩa: Quan hệ đã-xảy-ra-trước (→) giữa 2
sự kiện là mối quan hệ thứ tự nhỏ nhất thỏa
mãn các điều kiện sau:
▪ Nếu e xảy ra trước f trong cùng một tiến trình và
thời gian của e nhỏ hơn của f thì e → f
▪ Nếu e là sự kiện gửi của một thông điệp và f là sự
kiện nhận của cùng thông điệp đó (ở tiến trình
khác), thì e → f
▪ Nếu tồn tại một sự kiện g sao cho (e → g) và (g →
f), thì (e → f )

18
Mô hình
đã-xảy-ra-trước (4)
▪ Một tính toán (run) trong mô hình
đã-xảy-ra-trước được định nghĩa là một cặp
(E , →)
▪ E là tập tất cả các sự kiện
▪ → là thứ tự từng phần các sự kiện trên E

19
Sơ đồ tiến trình – thời gian hoặc Sơ đồ đã-xảy-ra-trước
e2 →e4 , e3 → f3 , và e1 →g4

20
Mô hình
đã-xảy-ra-trước (5)
▪ Trong sơ đồ tiến trình-thời gian, e → f khi và
chỉ khi có một đường dẫn trực tiếp từ sự kiện
e đến sự kiện f.
▪ Ngoài ra, hai sự kiện e và f có thể không liên
quan với nhau bởi mối quan hệ
đã-xảy-ra-trước
▪ Chúng ta nói rằng e và f là đồng thời (biểu
diễn bằng e || f) nếu ¬(e → f) ^ ¬(f → e)
▪ Trong ví dụ trước: e2 || f2, và e1 || g3

21
22
Những cơ chế
đồng hồ
Lưu vết mối quan hệ thứ tự thực hiện trên tập các sự
kiện
(Lưu dấu thời gian thứ tự thực hiện của các sự kiện)
Đồng hồ logic
Logical Clocks 23
Đồng hồ logic (1)
▪ Cơ chế cho phép chúng ta biết được thứ tự toàn
cục của các sự kiện có thể đã xảy ra thay vì thứ
tự toàn cục đã thực sự xảy ra
▪ Đồng hồ logic chỉ đưa ra thứ tự thực hiện giữa
các sự kiện
▪ Không sử dụng bất kỳ thuộc tính nào khác liên quan
tới thời gian vật lý
▪ Mỗi sự kiện sẽ được gắn với một số nguyên
dương
▪ Số này không liên quan đến thời gian vật lý thực sự
của sự kiện đó
24
Định nghĩa
Đồng hồ logic
▪ Một đồng hồ logic C là một ánh xạ từ tập các
sự kiện E đến 𝓝 (tập các số tự nhiên) với
rằng buộc:

Lưu ý: Chúng ta cũng có thể sử dụng trạng thái


của tiến trình thay cho sự kiện trong định nghĩa
trên, khi đó đồng hồ logic C phải thỏa mãn rằng
buộc:

25
Thuật toán cho
Đồng hồ logic (1)
▪ Thuật toán được miêu tả bằng những điều
kiện ban đầu và ba phương thức cho ba kiểu
sự kiện:
1. Sự kiện gửi thông điệp
2. Sự kiện nhận thông điệp
3. Sự kiện nội bộ
▪ Thuật toán sử dụng biến kiểu số nguyên c để
gán giá trị đồng hồ logic cho sự kiện hoặc
trạng thái
26
27
Thuật toán cho
Đồng hồ logic (2)
▪ Khi sự kiện gửi xảy ra, giá trị hiện tại của đồng hồ
được gửi cùng với thông điệp và sau đó giá trị này
tăng lên 1 đơn vị (dòng 14)
▪ Khi nhận được một thông điệp trả về (e.g. sự kiện
nhận), tiến trình nhận sẽ so sánh để lấy giá trị lớn
nhất trong 2 giá trị:
1. Giá trị đồng hồ hiện tại của nó và
2. Giá trị đồng hồ mà nó nhận được trong thông điệp
(dòng 17)
▪ Sau đó, tiến trình nhận tăng giá trị này lên 1 và gán
cho giá trị đồng hồ của nó
▪ Với một sự kiện nội bộ, tiến trình chỉ đơn giản tăng
giá trị đồng hồ của nó lên 1 (dòng 10)
28
Một tính toán với thuật
toán đồng hồ Logic

29
Đồng hồ Vector
Vector Clocks 30
Đồng hồ Vector
▪ Đồng hồ logic thỏa mã thuộc tính :

Tuy nhiên, điều ngược lại là không đúng !!!


C(s) < C(t) không ám chỉ rằng s → t
Do đó, đồng hồ logic không cung cấp thông tin
hoàn chỉnh về mối quan hệ đã-xảy-ra-trước
Cơ chế đồng hồ vector cho phép chúng ta nội
suy hoàn toàn mối quan hệ đã-xảy-ra-trước 31
Định nghĩa
Đồng hồ Vector (1)
Một đồng hồ vector v là một ánh xạ từ tập
trạng thái S đến Nk (vectơ của các số tự nhiên)
với rằng buộc:

trong đó s.v là vector được gán với trạng thái s


s.v[i] biểu thị giá trị/độ hiểu biết mà tiến trình s.p
biết về tiến trình i khi s.p đang ở trong trạng thái s

32
Định nghĩa
Đồng hồ Vector (2)
▪ Cho hai vector x và y có N chiều, chúng ta
định nghĩa phép so sánh sau:

33
Thuật toán Đồng hồ
vector

34
Thuật toán cho
Đồng hồ vector
▪ Tiến trình tăng giá trị đồng hồ vector của nó sau mỗi sự
kiện nội bộ
▪ Khi gửi thông điệp:
▪ Tiến trình gửi sẽ gửi kèm một bản sao đồng hồ vector của nó
trong thông điệp
▪ Sau đó, tiến trình gửi tăng giá trị thành phần của nó trong vector
lên 1 đơn vị
▪ Khi nhận thông điệp:
▪ Tiến trình nhận cập nhật đồng hồ vector bằng cách so sánh và lấy
giá trị lớn nhất giữa các thành phần trong đồng hồ vector của nó
và thành phần tương ứng trong đồng hồ vector nhận được
▪ Sau đó, tiến trình nhận tăng giá trị thành phần của nó trong
vector lên 1 đơn vị 35
Một tính toán với Thuật
toán đồng hồ vector

36
Đồng hồ phụ
thuộc trực tiếp
Direct-Dependency Clocks 37
Đồng hồ phụ thuộc trực
tiếp (1)
▪ Một hạn chế trong thuật toán đồng hồ vector
là yêu cầu O(N) số nguyên được gửi đi trong
mỗi thông điệp
▪ Đối với nhiều ứng dụng, có thể sử dụng một
phiên bản yếu hơn của đồng hồ vector gọi là
đồng hồ phụ-thuộc-trực-tiếp
▪ Chỉ yêu cầu một số nguyên được gắn thêm vào
mỗi thông điệp khi gửi đi

38
Đồng hồ phụ thuộc trực
tiếp (2)
Đồng hồ phụ-thuộc-trực-tiếp thỏa mãn rằng
buộc sau:

▪ Vị trí tương ứng với tiến trình gửi trong


vector của tiến trình gửi ở trạng thái s nhỏ
hơn hoặc bằng vị trí tương ứng với tiến trình
gửi trong vector của tiến trình nhận ở trạng
thái t
39
Thuật toán cho Đồng hồ
phụ thuộc trực tiếp
▪ Khi gửi thông điệp:
▪ Tiến trình gửi chỉ gửi kèm giá trị của thành phần đồng
hồ của nó, mà không phải là toàn bộ đồng hồ vector
▪ Sau khi gửi, tiến trình gửi sẽ tăng giá trị của thành phần
đồng hồ đó lên 1 đơn vị
▪ Khi nhận thông điệp, tiến trình nhận sẽ cập nhật 2
thành phần:
1. Thành phần đồng hồ của nó
2. Thành phần đồng hồ của tiến trình gửi
▪ Với các sự kiện nội bộ, thuật toán làm giống với
thuật toán đồng hồ vector
40
Thuận toán đồng hồ
phụ thuộc trực tiếp

41
42
Đồng hồ ma trận
Matrix Clocks 43
Đồng hồ ma trận (1)
▪ Sử dụng một ma trận N x N trong một hệ
thống phân tán với N tiến trình.
▪ Đồng hồ ma trận giúp biểu thị một mức độ
biết cao hơn so với đồng hồ vector
▪ Giá trị M[i,j] của tiến trình k biểu diễn điều
mà tiến trình k biết về “độ hiểu biết của
tiến trình i với tiến trình j”
▪ Ví dụ: nếu s.v[i, s.p] > k với mọi i, thì tiến
trình s.p có thể kết luận rằng mọi tiến trình
khác đã biết trạng thái hiện tại của nó lớn
hơn k

44
Thuật toán Đồng hồ ma
trận

45
Thuật toán cho
Đồng hồ ma trận
▪ Nếu ta chỉ tập trung vào hàng myId cho tiến trình PmyId,
thuật toán này sẽ trở thành thuật toán đồng hồ vector
▪ Khi gửi thông điệp, tiến trình gửi sẽ gửi kèm toàn bộ
ma trận
▪ Khi nhận thông điệp, tiến trình nhận sẽ cập nhật ma
trận:
▪ Bước 1: cập nhật giá trị tại các hàng khác myId
▪ Bước 2: cập nhật giá trị tại hàng myId với ma trận W nhận
được từ tiến trình srcId, chúng ta chỉ sử dụng hàng srcId của
ma trận W để cập nhật hàng myId

46
Tài liệu tham khảo
▪ Concurrent and Distributed Computing in Java,
Vijay K. Garg, University of Texas, John Wiley & Sons,
2005
▪ Tham khảo:
▪ Principles of Concurrent and Distributed Programming, M.
Ben-Ari, Second edition, 2006
▪ Foundations of Multithreaded, Parallel, and Distributed
Programming, Gregory R. Andrews, University of Arizona,
Addison-Wesley, 2000
▪ The SR Programming Language: Concurrency in Practice,
Benjamin/Cummings, 1993
▪ Xử lý song song và phân tán, Đoàn văn Ban, Nguyễn Mậu Hân,
Nhà xuất bản Khoa học và Kỹ thuật, 2009

47
LẬP
TRÌNH
BÀI 6:
ĐỒNG BÀI TOÁN TRUY CẬP
THỜI TÀI NGUYÊN CHỈA SẺ
& 1
PHÂN Giảng viên: Lê Nguyễn Tuấn Thành

TÁN Email: thanhlnt@tlu.edu.vn


NỘI DUNG
▪Bài toán loại trừ lẫn nhau trong hệ thống
phân tán
▪Những thuật toán dựa trên timestamp
▪Những thuật toán dựa trên token

Bài giảng có sử dụng hình vẽ trong cuốn sách “Concurrent and Distributed Computing in Java, Vijay K. Garg, 2
University of Texas, John Wiley & Sons, 2005”
Bài toán loại trừ lẫn nhau
trong hệ thống phân tán
▪ Xét hệ thống phân tán bao gồm một số lượng cố định tiến
trình và một tài nguyên chia sẻ
▪ Việc truy cập đến tài nguyên chia sẻ được coi là khu vực quan
trọng CS
▪ Yêu cầu: Đưa ra thuật toán để phối hợp truy cập tới tài
nguyên chia sẻ thỏa mãn 3 thuộc tính sau:
1. Safety: hai tiến trình không có quyền truy cập đồng thời vào CS
2. Liveness: bất kỳ yêu cầu nào tới CS cuối cùng phải được cấp
quyền
3. Fairness: những yêu cầu khác nhau phải được cấp quyền đi vào
CS theo thứ tự mà chúng được tạo ra
▪ Giả sử rằng không có lỗi trong hệ thống phân tán, các bộ xử
lý và liên kết giao tiếp là tin cậy
3
Giao diện Xử lý thông
điệp và Khoá

4
Những thuật
5
toán dựa trên
timestamp
Thuật toán mutex của
Lamport (1)
▪ Trong thuật toán này, mỗi tiến trình sẽ lưu giữ:
1. Một đồng hồ vector V (dùng để lưu dấu thời gian)
2. Một hàng đợi Q (dùng để lưu các yêu cầu đi vào CS của
các tiến trình trong hệ thống phân tán)
▪ Thuật toán này đảm bảo: các tiến trình đi vào CS
theo thứ tự dấu thời gian của yêu cầu ở phía tiến
trình gửi
▪ Chứ không phải thứ tự nhận được của yêu cầu bên phía
tiến trình nhận !
▪ Giả sử các thông điệp truyền đi theo thứ tự FIFO
6
Thuật toán mutex của
Lamport (2)
▪ Nếu hai yêu cầu có cùng một dấu thời gian, thì yêu
cầu của tiến trình có số hiệu nhỏ hơn được coi là
nhỏ hơn
▪ Một cách chính thức, Pi có thể đi vào CS nếu:

▪ q[i], q[j]: dấu thời gian của yêu cầu đi vào CS của hai
tiến trình Pi và Pj
▪ v[j]: dấu thời gian của thông điệp xác nhận từ tiến
tình Pj được ghi nhận ở tiến trình Pi
7
Các bước thực hiện (1)
1. Khi tiến trình Pi muốn đi vào CS
▪ Pi gửi thông điệp request có gắn dấu thời gian tới tất cả
tiến trình khác
▪ Đồng thời, Pi thêm yêu cầu có gắn dấu thời gian này vào
trong hàng đợi của nó
2. Khi một tiến trình Pk nhận được thông điệp
request từ tiến trình Pi
▪ Pk lưu yêu cầu này và dấu thời gian của yêu cầu trong
hàng đợi của nó
▪ Pk gửi ngược lại thông điệp ack (xác nhận) có gắn dấu
thời gian cho Pi
8
Các bước thực hiện (2)
3. Một tiến trình Pj nhận thấy nó có thể đi vào CS
khi và chỉ khi thoả mãn các điều kiện sau:
✔ Pj có một yêu cầu trong hàng đợi của nó với dấu thời gian
t nhỏ hơn tất cả các yêu cầu khác đang trong hàng đợi của

✔ Pj đã nhận thông điệp ack (xác nhận) từ tất cả tiến trình
khác với dấu thời gian lớn hơn t
4. Để giải phóng CS, tiến trình Pj gửi một thông
điệp release tới tất cả tiến trình khác
▪ Khi một tiến trình Pm nhận được thông điệp release, Pm
xoá yêu cầu tương ứng của Pj khỏi hàng đợi của nó
9
public class LamportMutex extends Process implements Lock {
public synchronized void requestCS() {
v.tick();
q[myId] = v.getValue(myId);
broadcastMsg("request", q[myId]);
while (!okayCS()) myWait();
}
public synchronized void releaseCS() {
q[myId] = Symbols.Infinity;
broadcastMsg("release", v.getValue(myId));
}
boolean okayCS() {
for (int j = 0; j < N; j++){
//REQ// if(isGreater(q[myId], myId, q[j], j)) return false;
//ACK// if(isGreater(q[myId], myId, v.getValue(j), j))return false;
}
return true;
}
public synchronized void handleMsg(Msg m, int src, String tag) {
int timeStamp = m.getMessageInt();
v.receiveAction(src, timeStamp);
if (tag.equals("request")) {
q[src] = timeStamp; sendMsg(src, "ack", v.getValue(myId));
} else if (tag.equals("release")) q[src] = Symbols.Infinity;
else if (tag.equals(”ack")) v[src] = timeStamp;
notify(); // okayCS() may be true now 10
}
Đánh giá thuật toán
mutex của Lamport
Sử dụng 3*(N-1) thông điệp cho mỗi lần yêu
cầu CS
▪ N - 1 thông điệp request
▪ N - 1 thông điệp ack (xác nhận)
▪ N - 1 thông điệp release

11
Thuật toán của Ricart và
Agrawala
▪ Sử dụng đồng hồ logic C và một hàng đợi pendingQ
▪ Kết hợp các chức năng của các thông điệp ack (xác
nhận) và thông điệp release thành thông điệp okay
▪ Trong thuật toán này, tiến trình Pk không phải lúc nào
cũng gửi thông điệp okay ngược lại khi nhận được một
thông điệp request từ tiến trình Pi
▪ Nó có thể trì hoãn xác nhận sau một khoảng thời gian
▪ Thuật toán chỉ sử dụng 2*(N-1) thông điệp cho mỗi lần
yêu cầu CS
▪ Thay vì 3*(N-1) thông điệp như thuật toán của Lamport

12
Các bước thực hiện (1)
1. Khi tiến trình Pi muốn yêu cầu CS (để sử dụng
tài nguyên chia sẻ)
▪ Pi gửi một thông điệp request gắn dấu thời gian tới tất
cả tiến trình khác
2. Khi tiến trình Pk nhận một thông điệp request
từ tiến trình gửi Pi
▪ Pk gửi một thông điệp okay nếu:
▪ Pk không quan tâm đến việc vào CS, hoặc
▪ Yêu cầu CS của Pk có dấu thời gian lớn hơn so với Pi
▪ Nếu không, yêu cầu của tiến trình gửi Pi sẽ được lưu
trong hàng đợi của Pk

13
Các bước thực hiện (2)
3. Một tiến trình Pj được đi vào CS khi:
✔ Pj đã yêu cầu tài nguyên chia sẻ bằng cách gửi
thông điệp request tới tất cả tiến trình khác, và
✔ Pj đã nhận được N-1 thông điệp okay từ N-1 tiến
trình khác xác nhận cho thông điệp request của

4. Khi tiến trình Pj giải phóng tài nguyên
▪ Pj gửi thông điệp okay cho các tiến trình đang
trong hàng đợi của Pj
14
public class RAMutex extends Process implements Lock {
public synchronized void requestCS() {
c.tick();
myts = c.getValue();
broadcastMsg("request", myts);
numOkay = 0;
while (numOkay < N-1) myWait();
}
public synchronized void releaseCS() {
myts = Symbols.Infinity;
while (!pendingQ.isEmpty()) {
int pid = pendingQ.removeHead();
sendMsg(pid, "okay", c.getValue());
}
}
public synchronized void handleMsg(Msg m, int src, String tag) {
int timeStamp = m.getMessageInt();
c.receiveAction(src, timeStamp);
if (tag.equals("request")) {
if ((myts == Symbols.Infinity ) || (timeStamp < myts)
||((timeStamp == myts)&&(src < myId)))//not interested in CS
sendMsg(src, "okay", c.getValue());
else pendingQ.add(src);
} else if (tag.equals("okay")) {
numOkay++;
if (numOkay == N - 1) notify(); // okayCS() may be true now 15
} } }
Những thuật
16
toán dựa trên
token
Thuật toán dựa trên
Token
▪Sử dụng một tài nguyên phụ, token, cho
những hệ thống phân tán với tài nguyên chia
sẻ
▪Nhiệm vụ: tạo, lưu giữ và luân chuyển yêu
cầu token giữa các tiến trình trong hệ thống
phân tán

17
Thuật toán mutex tập
trung
▪ Thuật toán ít tốn kém nhất cho bài toán loại trừ lẫn
nhau, dựa trên hàng đợi
▪ Thuật toán chỉ thoả mãn hai thuộc tính safety và liveness !
▪ Một trong số các tiến trình sẽ đóng vai trò là Người
lãnh đạo (Leader), hoặc Người điều phối (Coordinator)
cho việc đi vào CS
▪ Biến haveToken sẽ có giá trị là True cho tiến trình có
quyền truy cập tới CS
▪ Lúc đầu chỉ có haveToken của Leader là True
▪ haveToken của tất cả tiến trình khác là False
▪ Trong một thời điểm, chỉ có 1 tiến trình có giá trị
haveToken là True

18
Các bước thực hiện
1. Khi một tiến trình Pi muốn đi vào CS, nó sẽ gửi thông
điệp request đến tiến trình Leader
2. Khi nhận được các thông điệp request, tiến trình Leader
đặt những request này vào hàng đợi pendingQ của nó
3. Leader cấp quyền cho tiến trình Pk ở đầu hàng đợi bằng
cách gửi thông điệp okay cho Pk
4. Khi tiến trình Pk hoàn thành công việc trong CS của nó,
Pk gửi thông điệp release tới Leader
5. Khi nhận được thông điệp release, Leader gửi thông
điệp okay tới tiến trình tiếp theo trong hàng đợi
pendingQ, nếu hàng đợi không rỗng
▪ Nếu không, Leader đặt giá trị haveToken của nó thành True

19
public class CentMutex extends Process implements Lock {
public synchronized void requestCS() {
sendMsg(leader, "request");
while (!haveToken) myWait();
}
public synchronized void releaseCS() {
sendMsg(leader, "release");
haveToken = false;
}
public synchronized void handleMsg(Msg m, int src, String tag) {
if (tag.equals("request")) {
if (haveToken){
sendMsg(src, "okay");
haveToken = false;
}
else pendingQ.add(src);
} else if (tag.equals("release")) {
if (!pendingQ.isEmpty()) {
int pid = pendingQ.removeHead();
sendMsg(pid, "okay");
} else haveToken = true;
} else if (tag.equals("okay")) {
haveToken = true;
notify();
}
20
}
Đánh giá thuật toán
mutex tập trung
▪ Thuật toán mutex tập trung không thoả mãn thuộc
tính công bằng!
▪ Các yêu cầu NÊN được cấp quyền đi vào CS theo
thứ tự mà chúng được tạo ra chứ không phải theo thứ
tự mà chúng nhận được
▪ Giả sử rằng tiến trình Pi gửi yêu cầu đi vào CS cho
tiến trình Leader
▪ Sau đó một tiến trình Pj cũng gửi yêu cầu đi vào CS tới
Leader và yêu cầu của Pj đến tiến trình Leader sớm
hơn yêu cầu được tạo bởi tiến trình Pi
▪ Như vậy, thứ tự yêu cầu mà tiến trình Leader nhận
được có thể sẽ khác với thứ tự chúng được tạo ra !

21
Bài tập
▪ Đề xuất cải tiến thuật toán mutex tập trung
để thoả mãn thuộc tính công bằng

22
Thuật toán vòng tròn
token
▪Giả sử tất cả tiến trình được tổ chức theo một
hình tròn
▪Token lưu thông quanh vòng tròn
▪Tiến trình Pi muốn vào CS phải chờ đến khi
token được luân chuyển đến nó
▪ Khi đó Pi sẽ bắt lấy token và đi vào CS

23
public class CircToken extends Process implements Lock {
public synchronized void initiate() {
if (haveToken) sendToken();
}
public synchronized void requestCS() {
wantCS = true;
while (!haveToken) myWait();
}
public synchronized void releaseCS() {
wantCS = false;
sendToken();
}
void sendToken() {
. . .
}
public synchronized void handleMsg(Msg m, int src, String tag) {
if (tag.equals("token")) {
haveToken = true;
if (wantCS) notify();
else {
Util.mySleep(1000);
sendToken();
}
}
} 24
}
Tài liệu tham khảo
▪ Concurrent and Distributed Computing in Java,
Vijay K. Garg, University of Texas, John Wiley & Sons,
2005
▪ Tham khảo:
▪ Principles of Concurrent and Distributed Programming, M.
Ben-Ari, Second edition, 2006
▪ Foundations of Multithreaded, Parallel, and Distributed
Programming, Gregory R. Andrews, University of Arizona,
Addison-Wesley, 2000
▪ The SR Programming Language: Concurrency in Practice,
Benjamin/Cummings, 1993
▪ Xử lý song song và phân tán, Đoàn văn Ban, Nguyễn Mậu Hân,
Nhà xuất bản Khoa học và Kỹ thuật, 2009

25
LẬP
TRÌNH
BÀI 7:
ĐỒNG BÀI TOÁN SẮP THỨ
THỜI TỰ THÔNG ĐIỆP
& 1
PHÂN
TÁN Giảng viên: Lê Nguyễn Tuấn Thành
Email: thanhlnt@tlu.edu.vn
Tính không xác định (1)
▪ Các chương trình phân tán khó thiết kế và kiểm thử
bởi tính chất không xác định của nó
▪ Nguyên nhân: do thứ tự khác nhau của các thông điệp
trong mỗi lần thực thi
▪ Một tính toán bất đồng bộ hoàn toàn không có bất kỳ
giới hạn nào về thứ tự thông điệp
▪ Cho phép tối đa sự đồng thời
▪ Tuy nhiên: KHÓ thiết kế những thuật toán cho thứ
tự giao tiếp bất đồng bộ hoàn toàn
▪ Do các thuật toán này phải tính đến tất cả thứ tự có thể có
trong việc truyền thông điệp

2
Tính không xác định (2)
Mong muốn: kiểm soát tính chất không xác
định của các chương trình phân tán
▪ Bằng cách kiểm soát các kiểu thứ tự thông điệp
có thể có trong hệ thống phân tán

3
NỘI DUNG
▪ Thứ tự FIFO
▪ Thứ tự nhân quả
▪ Thứ tự đồng bộ
▪ Thứ tự toàn bộ cho thông điệp multicast
▪ Thuật toán tập trung
▪ Thuật toán của Lamport
▪ Thuật toán của Skeen

Bài giảng có sử dụng hình vẽ trong cuốn sách “Concurrent and Distributed Computing in Java, Vijay K. Garg, 4
University of Texas, John Wiley & Sons, 2005”
5
Thứ tự FIFO

FIFO ordering
Thứ tự FIFO
▪ Nhiều hệ thống phân tán giới hạn việc phân phối
thông điệp theo thứ tự FIFO
▪ Giúp đơn giản hoá thiết kế thuật toán
▪ Ví dụ: chúng ta đã sử dụng giả thiết thứ tự FIFO
trong thuật toán của Lamport cho bài toán truy cập tài
nguyên chia sẻ
▪ Tuy nhiên: chương trình sẽ mất đi một vài tính
chất đồng thời
▪ Khi nhận được một thông điệp không tuân theo thứ tự
FIFO, việc xử lý phải bị trì hoãn

6
Thứ tự FIFO
Định nghĩa
▪ 

7
Thứ tự FIFO
Thuật toán (1)
▪ Mỗi tiến trình lưu một ma trận M[1..N, 1..N]
▪ Phần tử M[j,k] tại tiến trình Pi lưu lại số lượng
thông điệp được gửi từ tiến trình Pj cho tiến trình
Pk, được biết bởi tiến trình Pi

8
Thứ tự FIFO
Thuật toán (2)
▪ 

9
10
Thứ tự nhân
quả
Causal ordering
Thứ tự nhân quả
▪ Một thứ tự thông điệp mạnh hơn FIFO
▪ Trực quan: một thông điệp không bị vượt qua bởi
một chuỗi các thông điệp khác
▪ Ví dụ: một thứ tự FIFO nhưng không phải thứ tự
nhân quả

11
Thứ tự Nhân quả
Định nghĩa
▪ 

12
Thứ tự nhân quả
Thuật toán (1)
▪ Tại mỗi tiến trình lưu một ma trận M[1..N, 1..N]
▪ Phần tử M[j,k] tại Pi lưu lại số lượng thông điệp
được gửi từ tiến trình Pj cho tiến trình Pk, được biết
bởi tiến trình Pi

13
Thứ tự nhân quả
Thuật toán (2)
▪ 

14
Mã giả cho Thuật toán
thứ tự nhân quả tại Pi

15
16
Thứ tự đồng bộ

Synchronous ordering
Thứ tự đồng bộ (1)
▪ Thứ tự này mạnh hơn thứ tự nhân quả
▪ Một tính toán thoả mãn thứ tự đồng bộ nếu tất cả
thông điệp được gửi & nhận một cách tức thời
▪ Dấu thời gian của sự kiện gửi và nhận thông điệp là giống
nhau
▪ Truyền thông điểm (point-to-point)

17
Thứ tự Đồng bộ Thứ tự không đồng bộ

18
Thứ tự đồng bộ (2)
▪ 

Điều kiện SYNC


Chứng minh: với bất kỳ 2 sự kiện e và f trong hệ
thống phân tán được sắp thứ tự đồng bộ, thì:
 

19
Thứ tự
Thứ tự Thứ tự Thứ tự
≥ ≥ ≥ bất đồng
đồng bộ nhân quả FIFO
bộ

20
Thứ tự đồng bộ
Thuật toán
▪ Thêm các thông điệp điều khiển (ack, request, permission)
để đảm bảo thứ tự đồng bộ
▪ Những thông điệp điều khiển này không cần tuân theo thứ tự
đồng bộ !
▪ Sử dụng 2 loại thông điệp
1. Thông điệp lớn: được gửi bởi tiến trình có định danh lớn
hơn tới tiến trình có định danh nhỏ hơn.
2. Thông điệp nhỏ: được gửi bởi tiến trình có định danh nhỏ
hơn tới tiến trình có định danh lớn hơn.
▪ Một tiến trình có thể ở trong 2 trạng thái:
1. active (chủ động)
2. passive (thụ động)
▪ Ban đầu tất cả tiến trình đều ở trạng thái active
21
Thứ tự đồng bộ
Thuật toán (3)
1. Tiến trình Pi ở trạng thái active có thể gửi một
thông điệp lớn (tới tiến trình Pj có định danh nhỏ
hơn, i > j)
▪ Sau khi gửi, Pi chuyển sang trạng thái passive cho đến khi
nhận được thông điệp ack từ tiến trình Pj
▪ Chú ý:
▪ Tiến trình ở trạng thái passive không thể gửi hoặc
nhận thông điệp, trừ khi đó là thông điệp ack

22
Thứ tự đồng bộ
Thuật toán (4)
2. Để tiến trình Pj gửi 1 thông điệp nhỏ tới tiến trình
Pi có định danh lớn hơn (j < i), Pj cần sự cho phép
từ Pi
▪ Pj có thể gửi thông điệp request bất kỳ lúc nào
▪ Pi chỉ có thể cho phép (gửi thông điệp permission) khi Pi
đang ở trạng thái active
▪ Sau đó, Pi chuyển sang trạng thái passive cho đến khi Pi
nhận thông điệp nhỏ từ Pj

23
Thuật toán thứ tự đồng bộ

24
Thứ tự toàn bộ
25
cho thông điệp
đa hướng
Total ordering for multicast messages
Thứ tự toàn bộ cho
thông điệp đa hướng
▪ Thứ tự toàn bộ:
▪ Nếu tiến trình Pi gửi 2 thông điệp đa hướng x, y tới các
tiến trình Pj, Pk,… thì tất cả những tiến trình này sẽ
nhận thông điệp theo cùng một thứ tự (x,y hoặc y, x)
▪ Lưu ý:
▪ Điều này không ám chỉ thứ tự đó là thứ tự Nhân quả hoặc
thậm chí FIFO
▪ Xét trường hợp khi Pi gửi 2 thông điệp: m1 và sau đó là m2
▪ Nếu tất cả tiến trình nhận m2 trước m1, thì thứ tự toàn bộ
được thỏa mãn, tuy nhiên không thoả mãn thứ tự FIFO
26
Thứ tự toàn bộ:
Thuật toán
▪Sử dụng lại các thuật toán cho truy cập tài
nguyên chia sẻ
▪ Thuật toán mutex tập trung
▪ Thuật toán của Lamport
▪Thuật toán của Skeen

27
Thuật toán tập trung
cho thứ tự toàn bộ
1. Khi tiến trình Pi muốn multicast 1 thông điệp
▪ Pi gửi thông điệp đó cho tiến trình điều phối
▪ Tiến trình điều phối lưu 1 hàng đợi các yêu cầu

2. Khi một yêu cầu, được gửi từ 1 tiến trình Pj nào


đó, có thể được thực hiện, tiến trình điều phối sẽ
multicast thông điệp đó

28
Thuật toán của Lamport
cho thứ tự toàn bộ
▪ Thay đổi thuật toán mutex của Lamport cho bài
toán sắp thứ tự toàn bộ, với giả thiết:
▪ Thứ tự FIFO giữa các thông điệp
▪ Một thông điệp được broadcast tới tất cả tiến trình khác

▪ Mô phỏng multicast bằng cách sử dụng các thông


điệp broadcast
▪ Mỗi tiến trình sẽ gồm có 2 vector:
▪ 1 đồng hồ vector (sử dụng cho dấu thời gian)
▪ 1 hàng đợi (lưu những thông điệp chưa được phân phối)

29
Thuật toán của Lamport:
Các bước thực hiện
1. Khi Pi muốn gửi thông điệp broadcast:
▪ Pi gửi thông điệp với dấu thời gian tới mọi tiến trình khác.

2. Khi Pj nhận được 1 thông điệp broadcast


▪ Thông điệp và dấu thời gian được lưu trong hàng đợi của
Pj
▪ Một thông điệp ack và dấu thời gian tương ứng được gửi
ngược về tiến trình gửi Pi
3. Một tiến trình Pk có thể phân phối thông điệp với
dấu thời gian t nhỏ nhất trong hàng đợi của nó nếu:
▪ Pk đã nhận được thông điệp ack có dấu thời gian lớn hơn t
từ tất cả các tiến trình khác 30
Thuật toán của Skeen
cho thứ tự toàn bộ
▪ Thuật toán chỉ yêu cầu số lượng thông điệp tương
ứng với số lượng tiến trình nhận (m)
▪ Thay vì N-1 tiến trình như thuật toán của Lamport

▪ Mỗi tiến trình lưu 1 đồng hồ logic

31
Thuật toán của Skeen:
Các bước thực hiện (1)
1. Khi tiến trình Pi muốn gửi 1 thông điệp multicast
▪ Pi gửi thông điệp với dấu thời gian tới những tiến trình
đích
2. Khi tiến trình Pk nhận được 1 thông điệp
▪ Pk đánh dấu thông điệp đó là chưa-thể-chuyển-đi
(undeliverable)
▪ Pk gửi ngược giá trị của đồng hồ logic của nó như 1 lời
đề xuất cho tiến trình gửi (Pi)

32
Thuật toán của Skeen:
Các bước thực hiện (2)
3. Khi tiến trình gửi Pi nhận được các lời đề xuất
gửi từ các tiến trình đích
▪ Pi lấy giá trị max của dấu thời gian trong tất cả các đề xuất,
gọi giá trị này là đề-xuất-cuối-cùng
▪ Pi gửi đề xuất cuối cùng này đến những tiến trình đích

4. Khi Pk nhận được đề xuất cuối cùng của một


thông điệp
▪ Pk đánh dấu thông điệp là có-thể-chuyển-đi (deliverable)
▪ Một thông điệp có thể được xử lý nếu nó có dấu thời gian
nhỏ nhất trong hàng đợi của Pk

33
P1

P2

P3

1. Tiến trình P0 multicast thông điệp msg tới tiến trình P1 và P2


2. Khi P1 và P2 nhận được thông điệp, chúng đánh dấu nó là
chưa-thể-chuyển-đi và gửi đề xuất với giá trị dấu thời gian
tương ứng là 2 và 4
3. P0 lấy giá trị lớn nhất của dấu thời gian đề xuất được gửi từ P1,
P2 và gửi đề-xuất-cuối-cùng (4) cho P1, P2
4. P1, P2 đánh dấu msg là có-thể-chuyển-đi và sẽ xử lý thông điệp
nếu nó có dấu thời gian nhỏ nhất trong hàng đợi 34
Tài liệu tham khảo
▪ Concurrent and Distributed Computing in Java,
Vijay K. Garg, University of Texas, John Wiley & Sons,
2005
▪ Tham khảo:
▪ Principles of Concurrent and Distributed Programming, M.
Ben-Ari, Second edition, 2006
▪ Foundations of Multithreaded, Parallel, and Distributed
Programming, Gregory R. Andrews, University of Arizona,
Addison-Wesley, 2000
▪ The SR Programming Language: Concurrency in Practice,
Benjamin/Cummings, 1993
▪ Xử lý song song và phân tán, Đoàn văn Ban, Nguyễn Mậu Hân,
Nhà xuất bản Khoa học và Kỹ thuật, 2009

35
LẬP
TRÌNH
ĐỒNG BÀI 8:
THỜI BÀI TOÁN BẦU CỬ
& 1
PHÂN
TÁN Giảng viên: Lê Nguyễn Tuấn Thành
Email: thanhlnt@tlu.edu.vn
NỘI DUNG
▪Bài toán bầu cử
▪Thuật toán dựa trên vòng tròn
▪Thuật toán Chang-Roberts
▪Thuật toán Hirschberg-Sinclair

Bài giảng có sử dụng hình vẽ trong cuốn sách “Concurrent and Distributed Computing in Java, Vijay K. Garg,
2
University of Texas, John Wiley & Sons, 2005”
Bài toán bầu cử
▪ Một bài toán quan trọng trong hệ thống phân
tán là Bài toán bầu cử tiến trình lãnh đạo
▪ Tiến trình lãnh đạo có thể được sử dụng như
người điều phối trong những thuật toán tập
trung cho bài toán mutex

3
Giao diện Election

▪ Phương thức getLeader() trả về định danh của tiến


trình được chọn là lãnh đạo
▪ Nếu định danh của tiến trình lãnh đạo chưa được
biết, thì phương thức này sẽ khóa cho đến khi
người lãnh đạo được chọn.

4
Bài toán bầu cử:
Giải pháp (1)
▪ Bài toán bầu cử người lãnh đạo tương tự như
bài toán loại trừ lẫn nhau
▪ Trong cả 2 bài toán, chúng ta đều quan tâm đến
việc chọn ra một trong số các tiến trình, được gọi
là tiến trình đặc quyền
▪ Các giải pháp dựa trên người điều phối cho
bài toán mutex không thể áp dụng cho bài
toán bầu cử người lãnh đạo
▪ Lý do: việc quyết định tiến trình nào đóng vai trò
người điều phối hoặc giữ token là tương đương với
bài toán bầu cử người lãnh đạo
5
Bài toán bầu cử:
Giải pháp (2)
▪ Thuật toán mutex của Lamport có thể áp
dụng cho bài toán bầu cử
▪ Tiến trình đầu tiên đi vào CS được xem là người
lãnh đạo
▪ Tuy nhiên thuật toán này không tổng quát,
do:
▪ Nền tảng giao tiếp mạng phía dưới phải kết nối
hoàn toàn
▪ Các thông điệp phải truyền đi theo thứ tự FIFO
▪ Mỗi tiến trình phải giao tiếp với mọi tiến trình khác
6
Bài toán bầu cử:
Giải pháp (3)
Trong trường hợp các tiến trình trong hệ thống
phân tán được sắp xếp theo hình tròn, tồn tại
các thuật toán hiệu quả hơn của bài toán bầu
cử

7
8
Thuật toán dựa
trên vòng tròn
Ring-based algorithms
Yêu cầu
▪Các thuật toán cho bài toán bầu cử
người lãnh đạo giả định rằng các tiến
trình có định danh duy nhất

9
Thuật toán của
Chang-Roberts
▪ Đảm bảo rằng tiến trình với định danh lớn
nhất được lựa chọn là tiến trình lãnh đạo
▪ Mỗi tiến trình:
▪ Chỉ gửi thông điệp cho hàng xóm bên trái của
nó và
▪ Chỉ nhận thông điệp từ hàng xóm bên phải
▪ Các tiến trình không biết được tổng số tiến
trình trong hệ thống, cũng như không biết
định danh của các tiến trình khác
10
Các bước thực hiện (1)
1. Mỗi tiến trình Pi gửi thông điệp tự ứng cử
(election) cùng với định danh của nó cho
tiến trình bên trái
▪ Nếu nó chưa nhận được thông điệp nào từ một
tiến trình với định danh cao hơn
2. Khi Pi nhận được thông điệp election từ
tiến trình bên phải:
▪ Tiến trình chuyển tiếp các thông điệp với id lớn
hơn id của nó sang bên trái
▪ Ngược lại (e.g id của thông điệp nhỏ hơn id của
nó), tiến trình nuốt thông điệp đó
11
Các bước thực hiện (2)
3. Nếu tiến trình Pk nhận lại được thông điệp
tự ứng cử (election) của mình
▪ Nó sẽ biết bản thân mình là tiến trình lãnh đạo và
thông báo bằng cách gửi thông điệp leader tới
tất cả tiến trình khác
4. Khi tiến trình Pk nhận lại thông điệp leader
của mình
▪ Nó hiểu rằng tất cả tiến trình khác đều đã biết nó
là tiến trình lãnh đạo

12
public class RingLeader extends Process implements Election {
int number; int leaderId = -1; int next;
boolean awake = false;

public synchronized int getLeader(){
while (leaderId == -1) myWait();
return leaderId;
}
public synchronized void handleMsg(Msg m, int src, String tag) {
int j = m.getMessageInt(); // get the number
if (tag.equals("election")) {
if (j > number)
sendMsg(next, "election", j); // forward the message
else if (j == number) // I won!
sendMsg(next, "leader", myId);
else if ((j < number) && !awake) startElection();
} else if (tag.equals("leader")) {
leaderId = j;
notify();
if (j != myId) sendMsg(next, "leader", j);
}
}
public synchronized void startElection() {
awake = true;
sendMsg(next, "election", number);
} 13

}
Đánh giá: trường hợp tồi
nhất & tốt nhất
Độ phức tạp thông điệp trong trường hợp xấu
nhất

14
Độ phức tạp trung bình O(N log
Thuật toán của
Hirschberg-Sinclair (1)
▪ Giả sử việc truyền thông trên vòng tròn theo
2 chiều
▪ Có thể gửi thông điệp sang bên trái hoặc bên phải

▪ Ý tưởng: thực hiện việc bầu cử trên một tập


con tiến trình với số lượng tăng dần sau các
vòng bầu cử
▪ Một tiến trình Pi cố gắng bầu cho nó ở vòng r
▪ Chỉ những tiến trình thắng ở vòng r mới có thể tiến
vào vòng r+1

15
Thuật toán của
Hirschberg-Sinclair (2)
▪ Tiến trình Pi là 1 tiến trình lãnh đạo ở vòng r khi và
chỉ khi Pi có định danh lớn nhất trong tất cả các tiến
trình với khoảng cách nhỏ hơn hoặc bằng 2r tính từ Pi
▪ Hai tiến trình được bầu là lãnh đạo sau vòng r phải
có khoảng cách ít nhất là 2r
▪ Sau vòng r, có nhiều nhất N/(2r-1 + 1) tiến trình lãnh
đạo
▪ Sau mỗi vòng, số lượng tiến trình lãnh đạo giảm đi,
và sau O(log N) vòng chỉ còn chính xác 1 tiến trình
lãnh đạo
▪ Ở mỗi vòng có nhiều nhất O(N) thông điệp, do đó
16
tổng số thông điệp là O(N log N)
Ví dụ
▪ Khởi đầu:
▪ Tất cả tiến trình đều là
người lãnh đạo
▪ Vòng 0:
▪ 6, 7, và 8 là người lãnh đạo

▪ Vòng 1:
▪ 7, 8 là người lãnh đạo

▪ Vòng 2:
▪ 8 là người lãnh đạo duy
nhất
17
Tài liệu tham khảo
▪ Concurrent and Distributed Computing in Java,
Vijay K. Garg, University of Texas, John Wiley & Sons,
2005
▪ Tham khảo:
▪ Principles of Concurrent and Distributed Programming, M.
Ben-Ari, Second edition, 2006
▪ Foundations of Multithreaded, Parallel, and Distributed
Programming, Gregory R. Andrews, University of Arizona,
Addison-Wesley, 2000
▪ The SR Programming Language: Concurrency in Practice,
Benjamin/Cummings, 1993
▪ Xử lý song song và phân tán, Đoàn văn Ban, Nguyễn Mậu Hân,
Nhà xuất bản Khoa học và Kỹ thuật, 2009

18

You might also like