1 12/5/2015 chapter 7: Process Synchronization 进程同步.

79
1 03/29/22 chapter 7: Process Synchronization 进进进进

Transcript of 1 12/5/2015 chapter 7: Process Synchronization 进程同步.

1 04/18/23

chapter 7: Process Synchronization

进程同步

2 04/18/23

协作进程

通过共享逻辑地址空间共享代码和数据 通过共享文件共享数据 共享数据会导致数据不一致性问题

3 04/18/23

chapter 7: Process Synchronization

Background 背景 The Critical-Section Problem 临界区问题 Synchronization Hardware 同步的硬件实现 Semaphores信号量

4 04/18/23

Classical Problems of Synchronization经典同步问题 Monitors 管程 Java SynchronizationJava中的同步机制 Synchronization in Solaris 2 Solaris 2的同步机制 Synchronization in Windows NT Windows NT的同步机制

5 04/18/23

Background

Concurrent access to shared data may result in data inconsistency(对共享数据的并发访问可能导致数据的不一致性) .

Maintaining data consistency requires mechanisms to ensure the orderly execution of cooperating processes(要保持数据的一致性,就需要一种保证并发进程的正确执行顺序的机制) .

6 04/18/23

例:共享内存问题

Shared-memory solution to bounded-butter problem (Chapter 4) has a race condition on the class data count

[ 第 4 章 P83中 ]解决有界缓冲区问题的共享内存方法,对循环队列的操作,我们在此引入一变量, count,表示缓冲池中空闲块的数目。

7 04/18/23

Bounded-Buffer

Shared data#define BUFFER_SIZE 10typedef struct {. . .

} item;item buffer[BUFFER_SIZE];int in = 0;int out = 0;int counter = 0;

8 04/18/23

Bounded-Buffer

Producer process item nextProduced;while (1) {

while (counter == BUFFER_SIZE); /* do nothing */

buffer[in] = nextProduced;in = (in + 1) % BUFFER_SIZE;counter++;

}

9 04/18/23

Bounded-Buffer

Consumer process item nextConsumed;while (1) {

while (counter == 0); /* do nothing */

nextConsumed = buffer[out];out = (out + 1) % BUFFER_SIZE;counter--;

}

10 04/18/23

Bounded Buffer

The statements

counter++;counter--;must be performed atomically.

Atomic operation means an operation that completes in its entirety without interruption.

11 04/18/23

Bounded Buffer

The statement “count++” may be implemented in machine language as:

register1 = counterregister1 = register1 + 1counter = register1

12 04/18/23

The statement “count—” may be implemented as:

register2 = counterregister2 = register2 – 1counter = register2

13 04/18/23

Bounded Buffer

If both the producer and consumer attempt to update the buffer concurrently, the assembly language statements may get interleaved(交错) .

Interleaving depends upon how the producer and consumer processes are scheduled.

14 04/18/23

Bounded Buffer

Assume counter is initially 5. One interleaving of statements is:

producer: register1 = counter (register1 = 5)producer: register1 = register1 + 1 (register1 = 6)consumer: register2 = counter (register2 = 5)consumer: register2 = register2 – 1 (register2 = 4)producer: counter = register1 (counter = 6)consumer: counter = register2 (counter = 4)

The value of count may be either 4 or 6, where the correct result should be 5.

15 04/18/23

Race Condition竟争条件

Race condition: The situation where several processes access – and manipulate shared data concurrently. The final value of the shared data depends upon which process finishes last.

To prevent race conditions, concurrent processes must be synchronized.

16 04/18/23

The Critical-Section Problem

n processes all competing to use some shared data

Each process has a code segment, called critical section, in which the shared data is accessed.

Problem – ensure that when one process is executing in its critical section, no other process is allowed to execute in its critical section.

17 04/18/23

Solution to Critical-Section Problem

1. Mutual Exclusion. If process Pi is executing in its critical section, then no other processes can be executing in their critical sections

2.Progress. If no process is executing in its critical section and there exist some processes that wish to enter their critical section, then the selection of the processes that will enter the critical section next cannot be postponed indefinitely

18 04/18/23

3. Bounded Waiting. A bound must exist on the number of times that other processes are allowed to enter their critical sections after a process has made a request to enter its critical section and before that request is granted.

19 04/18/23

互斥条件。假定进程 Pi在其临界区内执行,其他任何进程将被排斥在自己的临界区之外 .

有空让进。临界区虽没有进程执行,但有些进程需要进入临界区,不能无限期地延长下一个要进入临界区进程的等待时间 .

有限等待。在一个进程提出进入临界区的请求和该请求得到答复的时间内,其他进程进入临界区前的等待时间必须是有限的

20 04/18/23

进程同步问题解必须遵循:

Assume that each process executes at a nonzero speed (假定每个进程都以非零的的速率执行) .

No assumption concerning relative speed of the n processes(没有任何关于这 n 个进程相对执行速率的假定) .

21 04/18/23

Initial Attempts to Solve Problem

General structure of process Pi (other process Pj)

do {entry section

critical sectionexit section

reminder section} while (1);

22 04/18/23

Two-process solutions

Only 2 processes, P0 and P1

Processes may share some common variables to synchronize their actions.

23 04/18/23

Algorithm 1

Shared variables: int turn;initially turn = 0

turn =i Pi can enter its critical section Process Pi

do {while (turn != i) ;critical section

turn = j;reminder section

} while (1); Satisfies mutual exclusion, but not progress

24 04/18/23

Algorithm 2 Shared variables

boolean flag[2];initially flag [0] = flag [1] = false.

flag [i] = true Pi ready to enter its critical section

Process Pi

do {flag[i] := true;while (flag[j]) ;critical sectionflag [i] = false;remainder section} while (1);

Satisfies mutual exclusion, but not progress requirement.

25 04/18/23

Algorithm 3 Combined shared variables of algorithms 1 and 2.

Process Pi

do {flag [i]:= true;turn = j;while (flag [j] and turn = j) ;critical section

flag [i] = false;remainder section

} while (1); Meets all three requirements; solves the critical-section problem for two processes.

26 04/18/23

Bakery Algorithm

Before entering its critical section, process receives a number. Holder of the smallest number enters the critical section.

If processes Pi and Pj receive the same number, if i < j, then Pi is served first; else Pj is served first.

The numbering scheme always generates numbers in increasing order of enumeration; i.e., 1,2,3,3,3,3,4,5...

Critical section for n processes

27 04/18/23

Bakery Algorithm

Notation < lexicographical order (ticket #, process id #) (a,b) < c,d) if a < c or if a = c and b < d max (a0,…, an-1) is a number, k, such that k

ai for i - 0, …, n – 1

Shared databoolean choosing[n];int number[n];

Data structures are initialized to false and 0 respectively

28 04/18/23

Bakery Algorithm do { choosing[i] = true;number[i] = max(number[0], number[1], …, number [n – 1])+1;choosing[i] = false;for (j = 0; j < n; j++) {

while (choosing[j]) ; while ((number[j] != 0) &&

(number[j],j) < number[i],i)) ;}

critical sectionnumber[i] = 0;

remainder section} while (1);

29 04/18/23

Synchronization Hardware

Test and modify the content of a word atomically.

boolean TestAndSet(boolean &target) {

boolean rv = target;tqrget = true;

return rv;}

30 04/18/23

Semaphore

Semaphore S – integer variable(信号量 S – 整型变量 spinlock自旋锁)

Apart from initialization, semaphore S can only be accessed via two indivisible (atomic) operations(除初始化外,仅能通过两个不可分割的[原子 ]操作访问)

wait(S):while S 0 do no-op;S--;

signal(S): S++;

31 04/18/23

Critical Section of n Processes

Shared data: semaphore mutex; //initially mutex = 1

Process Pi:

do { wait(mutex); critical section

signal(mutex); remainder section} while (1);

32 04/18/23

Usage semphores to solve synchronization

用信号量解决同步问题的一般框架 P1 :… S1

signal(synch); P2: … wait(synch); S2

S1 S2

33 04/18/23

Semaphore Implementation

Define a semaphore as a recordtypedef struct { int value; struct process *L;} semaphore;

Assume two simple operations: block suspends the process that invokes it.

wakeup(P) resumes the execution of a blocked process P.

这两操作都是由操作系统提供系统调用实现。

34 04/18/23

Implementation

Semaphore operations now defined as wait(S):

S.value--;if (S.value < 0) {

add this process to S.L;block;

}

signal(S): S.value++;if (S.value <= 0) {

remove a process P from S.L;wakeup(P);

}

35 04/18/23

信号量的关键之处是它们原子地执行,必须保证没有两个进程能同时对信号量执行wait(),signal()操作。 在单处理器下,可以在执行操作wait(),signal()时简单地禁止中断,这是因为一旦禁止中断,在单处理器下,不同的指令不会交织在一起,但在多处理器下,禁止中断是毫无作用的,来自不同进程的指令可以以任何方式交织在一起。

信号量的值为负时,其绝对值为在该信号量下等待的进程数目。

36 04/18/23

死锁和饥饿 死锁 – 两个或多个进程无限期地等待一个事件的

发生,而该事件正是由其中的一个等待进程引起的) . Let S and Q be two semaphores initialized to 1( S 和 Q 是两个初值为 1的信号量)

P0 P1

P(S); P(Q);P(Q); P(S);

V(S); V(Q);V(Q) V(S);

37 04/18/23

死锁和饥饿

Starvation – indefinite blocking. A process may never be removed from the semaphore queue in which it is suspended(饥饿 – 无限期地阻塞。进程可能永远无法从它等待的信号量队列中移去) .

38 04/18/23

Two Types of Semaphores

Counting semaphore – integer value can range over an unrestricted domain(计数信号量 – 变化范围没有限制的整型值) .

Binary semaphore – integer value can range only between 0 and 1; can be simpler to implement(二值信号量 – 变化范围仅限于 0和 1的信号量;容易实现).

Can implement a counting semaphore S as a binary semaphore(可以将计数信号量S用作二值信号量).

39 04/18/23

Implementing S

wait operationwait(S1);C--;if (C < 0) {

signal(S1);wait(S2);

}signal(S1);

signal operationwait(S1);C ++;if (C <= 0)

signal(S2);else

signal(S1);

40 04/18/23

Classical Problems of Synchronization

Bounded-Buffer Problem (有限缓冲区问题) Readers and Writers Problem (读者写者问题) Dining-Philosophers Problem (哲学家就餐问题)

41 04/18/23

Bounded-Buffer Problem

Shared data

semaphore full, empty, mutex;

Initially:

full = 0, empty = n, mutex = 1

42 04/18/23

Bounded-Buffer Problem Producer Process

do { …

produce an item in nextp …

wait(empty);wait(mutex); …

add nextp to buffer …

signal(mutex);signal(full);

} while (1);

43 04/18/23

Bounded-Buffer Problem Consumer Process

do { wait(full)wait(mutex); …remove an item from buffer to nextc …signal(mutex);signal(empty); …consume the item in nextc …

} while (1);

44 04/18/23

Readers-Writers Problem

第一类读者问题:没有要求有读者需要等待除非一个写者已被允许使用共享对象。

第二类读者问题:只要有一个写者在等待访问对象,那么不会有新的读者开始读操作。

二类读者写者问题都可能导致饥饿。

Shared datasemaphore mutex, wrt;Initiallymutex = 1, wrt = 1, readcount = 0

45 04/18/23

Readers-Writers Problem Writer Process

wait(wrt); …

writing is performed …

signal(wrt);

46 04/18/23

Readers-Writers Problem Reader Process

wait(mutex);readcount++;if (readcount == 1)

wait(wrt);signal(mutex);

…reading is performed …

wait(mutex);readcount--;if (readcount == 0)signal(wrt);

signal(mutex):

47 04/18/23

Dining-Philosophers Problem

Shared data semaphore chopstick[5];

Initially all values are 1

48 04/18/23

Dining-Philosophers Problem

Philosopher i:do {wait(chopstick[i])wait(chopstick[(i+1) % 5]) …eat …

signal(chopstick[i]);signal(chopstick[(i+1) % 5]); …think …

} while (1);

49 04/18/23

Monitors A monitor is a high-level abstraction that provides thread safety(管程是对提供线程安全机制的高度抽象) .

Only one thread may be active within the monitor at a time(任一时刻在管程中只有一个线程是能运行的) .

50 04/18/23

管程的抽象类型定义monitor monitor-name

{shared variable declarationsprocedure body P1 (…) {

. . .}

procedure body P2 (…) {. . .

} procedure body Pn (…) {

. . .}

{ initialization code}

}

51 04/18/23

Condition Variables

condition x, y;

A thread that invokes x.wait is suspended until another thread invokes x.signal(调用 x.wait的线程将一直等待到有另一个线程 调用x.signal)

52 04/18/23

管程定义

53 04/18/23

Monitor With Condition Variables

54 04/18/23

Dining Philosophers Example

monitor dp {

enum {thinking, hungry, eating} state[5];

condition self[5];void pickup(int i) void putdown(int i)void test(int i) void init() {

for (int i = 0; i < 5; i++)state[i] = thinking;

}}

55 04/18/23

Dining Philosophers

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 neighborstest((i+4) % 5);test((i+1) % 5);

}

56 04/18/23

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();

}}

57 04/18/23

Java Synchronization

Synchronized, wait(), notify() statements(同步化, wait(), notify()语句)

Multiple Notifications(多重声明) Block Synchronization(大块程序的同步化)

Java Semaphores( Java信号量) Java Monitors( Java管程)

58 04/18/23

synchronized Statement

Every object has a lock associated with it(每个对象都有与之相关联的锁) .

Calling a synchronized method requires “owning” the lock(只有拥有这把锁的方法才能称为同步化进程) .

If a calling thread does not own the lock (another thread already owns it), the calling thread is placed in the wait set for the object’s lock(如果主调线程没有这把锁, [而其他线程有了 ],主调线程就会进入该物体的等待集)

The lock is released when a thread exits the synchronized method(当线程退出了同步化方法时锁就会释放).

59 04/18/23

Entry Set

60 04/18/23

synchronized enter() Method

public synchronized void enter(Object item) {while (count == BUFFER_SIZE)

Thread.yield();++count;buffer[in] = item;in = (in + 1) % BUFFER_SIZE;

}

61 04/18/23

synchronized remove() Method

public synchronized Object remove() {Object item;while (count == 0)

Thread.yield();--count;item = buffer[out];out = (out + 1) % BUFFER_SIZE;return item;

}

62 04/18/23

The wait() Method

When a thread calls wait(), the following occurs(当线程调用 wait()时,会产生以下动作) :- the thread releases the object lock(该线程释放对象锁) .- thread state is set to blocked(线程状态置为阻塞) .- thread is placed in the wait set(线程进入等待集) .

63 04/18/23

Entry and Wait Sets

64 04/18/23

The notify() Method

When a thread calls notify(), the following occurs(当线程调用 notify()时,会产生以下动作) :- selects an arbitrary thread T from the wait set(任意从等待集中选出一个线程 T.- moves T to the entry set(将 T 置入入口集).- sets T to Runnable(设置T 为可运行状态).

T can now compete for the object’s lock again(此时,T 又能竞争使用对象锁了).

65 04/18/23

enter() with wait/notify Methods

public synchronized void enter(Object item) {while (count == BUFFER_SIZE)

try {wait();

} catch (InterruptedException e) { }

}++count;buffer[in] = item;in = (in + 1) % BUFFER_SIZE;notify();

}

66 04/18/23

remove() with wait/notify Methods

public synchronized Object remove() {Object item;while (count == 0)

try {wait();}catch (InterruptedException e) { }

--count;item = buffer[out];out = (out + 1) % BUFFER_SIZE;notify();return item;

}

67 04/18/23

Multiple Notifications

notify() selects an arbitrary thread from the wait set. *This may not be the thread that you want to be selected ( notify()从等待集中任意选取一个线程。这可能导致所选的线程并不是你想要的) .

Java does not allow you to specify the thread to be selected ( Java不容许你指定想要选取的线程) .

notifyAll() removes ALL threads from the wait set and places them in the entry set. This allows the threads to decide among themselves who should proceed next ( notifyAll()将等待集中所有的线程移至入口集。这就可以由他们自己决定让谁接着运行) .

notifyAll() is a conservative strategy that works best when multiple threads may be in the wait set ( notifyAll()是较保守的策略,只有在多线程可能在等待集的时候最有效) .

68 04/18/23

Reader Methods with Java Synchronization

public class Database { public Database() { readerCount = 0; dbReading = false; dbWriting = false; }

public synchronized int startRead() { /* see next slides */ }public synchronized int endRead() { /* see next slides */ }public synchronized void startWrite() { /* see next slides */ }

public synchronized void endWrite() { /* see next slides */ }

private int readerCount; private boolean dbReading; private boolean dbWriting;}

69 04/18/23

startRead() Method

public synchronized int startRead() { while (dbWriting == true) {

try {wait();

}catch (InterruptedException e) { }++readerCount;if (readerCount == 1)

dbReading = true;return readerCount;

}

70 04/18/23

endRead() Method

public synchronized int endRead() {

--readerCount if (readerCount == 0) db.notifyAll(); return readerCount; }

71 04/18/23

Writer Methods

public void startWrite() { while (dbReading == true || dbWriting == true)

try {wait();

}catch (InterruptedException e) { }dbWriting = true;

}

public void endWrite() {dbWriting = false;notifyAll();

}

72 04/18/23

Block Synchronization

Blocks of code – rather than entire methods – may be declared as synchronized(宣称同步化的往往是成块的程序代码而不是全部的方法)

This yields a lock scope that is typically smaller than a synchronized method(这将产生出典型的比同步化方法小的锁定范围) .

73 04/18/23

Block Synchronization (cont)

Object mutexLock = new Object();. . .public void someMethod() {// non-critical sectionsynchronized(mutexLock) {// critical section}// non-critical section

}

74 04/18/23

Java Semaphores

Java does not provide a semaphore, but a basic semaphore can be constructed using Java synchronization mechanism ( Java不提供信号量,但是可以用 Java同步机制来建构基本信号量).

75 04/18/23

Semaphore Class

public class Semaphore { public Semaphore() {

value = 0; }

public Semaphore(int v) { value = v;

} public synchronized void P() { /* see next slide */

}public synchronized void V() { /* see next slide */ }

private int value;}

76 04/18/23

P() Operation

public synchronized void P() { while (value <= 0) { try { wait(); } catch (InterruptedException e) { } } value --; }

77 04/18/23

V() Operation

public synchronized void V() { ++value; notify(); }

78 04/18/23

Solaris 2 Synchronization

Solaris 2 Provides( Solaris 2提供):- adaptive mutex(可变互斥量)

- condition variables(环境变量)

- semaphores(信号量)

- reader-writer locks(读–写锁)

79 04/18/23

Windows NT Synchronization

Windows NT Provides( Windows NT提供):

- mutex(互斥量)

- critical sections(临界区)

- semaphores(信号量)

- event objects(事件对象)