操作系统——Process Synchronization
211复习资料
1. 背景
让进程同步/一部执行,同时发生的access会导致data inconsistency。要保证cooperating processes 的执行顺序。
- eg. producer-consumer模型用count计数会遇到race condition
2. Critical Section Problem
- n processes{p0,p1,p2...pn-1},每个process都有critical section。
- 每个进程都要ask permission in entry section进入critical section
- 每个进程都要exit section再进入remainer section
-
do{ entry section critical section exit section remainder section }
三个要求:mutual exclusion: if process Pi is excuting in its critical section then...
- progress: if no process is executing in its critical section and there exist some processes that wish to enter their critical section...
- bounded waiting: the number of times that other processes are allowed to enter their critical sections...
- 两个方法:preemptive(real time sys) and non preemptive(free of race conditions in kernel mode)
- Peterson's Solution:
- load/store are atomic(cannot be interrupted)
- two process share two variables: int turn; boolean flag[2];
-
int turn = 0; boolean flag[2] = {false}; while(true){ flag[i] = true; turn = j; while(flag[j] && turn == j);
//critical section
flag[i] = false; }
Proof: multual exclusion: assume both Pi and Pj are in there CS. then flag[j] = flag[i] = true; the test for entry can not be true for both processes at the same time, therefore one process must jave enyered its CS first. P1 cound not have found turn = 1 and therefore cound not have entered its CS.
-
-
-
-
- progress: Case I: (Stuck)
P1 is not interested in entering its CS
- then flag[1] = false
- hence the while loop is false for P0 and it can goCase II: (Deadlock)
P1 is also blocked at the while loop
- impossible, because turn = 0 or 1
- hence the while loop is false for some process and it can go - waiting: Case III: (Starvation)
P1 is executing its CS repeatedly
- upon exiting its CS, P1 sets flag[1] = false
- hence the while loop is false for P0 and it can go (sufficient?)However, P1 may attempt to re-enter its CS before P0 has a chance to run.
- but to re-enter, P1 sets flag[1] to true and sets turn to 0
- hence the while loop is true for P1 and it waits
- the while loop is now false for P0 and it can go
- progress: Case I: (Stuck)
-
-
-
- 硬件 同步
- 解决办法基于locking
- Uniprocessors - could disable interrupts. 没有效率
- atomic hardware structions
- using lock:
do{ 获取lock cs 释放lock rs }while(true)
- test and set :返回目标状态,并将它置为true
boolean Test_and_Set (boolean *target) { boolean rv = *target; *target = TRUE; return rv: }
- 用test and set: 如果锁为false,进入CS,并打开锁,用完后关闭锁
do { while (Test_and_Set(&lock)); /* do nothing */ /* critical section */ lock = false; /* remainder section */ } while (true);
- Compare and swap: 返回value,如果与expect不同并将它置为new value
int Compare_and_Swap(int *value, int expected, int new value) { int temp = *value; if (*value == expected) *value = new value; return temp; }
用compare and swap:同理
do { while (compare_and_swap(&lock, 0, 1) != 0); /* do nothing */ /* critical section */ lock = 0; /* remainder section */ } while (true);
- 用test and set写限制长度的互斥:将waiting的数组i置为true,key置为ture,如果都对,对lock使用testandset。进入CS。如果j(i的下一个)和i不等,且jwaiting为true,当j和它下一个相等,如果j = i lock就释放,否则waiting【j】=false; 进入RS
do { waiting[i] = true; key = true; while (waiting[i] && key) key = Test_and_Set(&lock); waiting[i] = false; /* critical section */ j = (i + 1) % n; while ((j != i) && !waiting[j]) j = (j + 1) % n; if (j == i) lock = false; else waiting[j] = false; /* remainder section */ } while (true);
- 软件 同步
- mutex lock:acquire() release() 会造成busy waiting,也成为自旋锁
-
acquire() { while (!available); /* busy wait */ available = false;; } release() { available = true; }
- semaphore:不一定需要busy waiting
-
- S: wait()/P() signal()/V()
-
wait (S) { while (S <= 0); // busy wait S--; } signal (S) { S++; }
- no busy waiting
-
typedef struct{ int value; struct process *list; } semaphore; wait(semaphore *S) { S->value--; if (S->value < 0) { add this process to S->list; block(); } } signal(semaphore *S) { S->value++; if (S->value <= 0) { remove a process P from S->list; wakeup(P); } }
-
- Bounded-Buffer Problem
- P: C时交换full和empty
do { ... /* produce an item in next_produced */ ... wait(empty); wait(mutex); ... /* add next produced to the buffer */ ... signal(mutex); signal(full); } while (true);
- P: C时交换full和empty
- Readers-Writers Problem
- 用数据集的方式解决并行问题-reader writer lock
- variation:no reader kept waiting unless writer has permission already to use shared object.
-
- 作家准备好就写。
-
- 共享的数据有三个:rw_mutex = 1 //当第一个/最后一个读者
-
-
- mutex = 1 //用于保证read_count互斥性
- read_count = 0 //
- writer:每次rw_mutex-1,写完后再+1
-
writer: do { wait(rw_mutex); ... /* writing is performed */ ... signal(rw_mutex); } while (true);
reader: mutex-1, read+1,如果read=1,rw_mutex-1,mutex+1。
- 开始读
- mutex-1,read-1,如果read=0,就rw_mutex+1. mutex+1.
-
do { wait(mutex); read count++; if (read count == 1) wait(rw_mutex); signal(mutex); . .. /* reading is performed */ wait(mutex); read count--; if (read_count == 0) signal(rw_mutex); signal(mutex); } while (true);
- 即:作家写作前暂停读者,写完后释放。读者读书前先锁上mutex,排队,如果就剩1个读者了,rw-1,解开锁开始读书,读完后锁上mutex,read数-1,如果到0了,就rw+1,释放mutex。
-
-
- 哲学家:数据集:饭;筷子(每人一个)
-
- 等待筷子,等待右边的筷子,吃,放筷子,放右边的筷子;
-
do { wait ( chopstick[i] ); wait ( chopStick[ (i + 1) % 5] ); // eat signal ( chopstick[i] ); signal (chopstick[ (i + 1) % 5] ); // think } while (TRUE);
这个算法会导致哲学家都吃不上饭——都在等右边的筷子,或者饿死
- 用moniter:lock/zero or more条件(queue)//更抽象,内部只有一个进程执行
- pickup()自己饿了,吃一个试试,如果失败了,就等等
- 吃完后放筷子,思考
- 试着吃时如果左右没在吃,就吃,并signal自己
- 初始大家都在思考。
-

浙公网安备 33010602011771号