进程同步 并发性带来了异步性,有时候需要用进程同步来解决异步性。 有的进程之间需要相互配合完成工作,各进程的工作推进需要遵循一定的先后顺序。
信号量机制实现同步 信号量机制是一种用于进程同步的机制,它可以用来控制进程的执行顺序。 以下是实现code4需要code2完成的信号量机制:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 semaphore s = 1 ; P1() { code1; code2; V(s); code3; } P2() { P(s); code4; code5; }
管程机制实现同步 管程机制是一种用于进程同步的机制,它可以用来控制进程的执行顺序。管程有点类似C语言中封装的思想,将多个进程的共享数据和操作封装在一个管程中,然后通过调用管程中的方法来实现进程的同步。管程中的方法只能同时被一个进程调用,其他进程只能等待。这个是硬件上实现的,程序员不需要考虑。 以下是实现code4需要code2完成的管程机制:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 class monitor { condition c; void code2 () { code2; c.signal(); } void code4 () { c.wait(); code4; } } monitor M { condition c; code1; code2; c.signal(); code3; } P1() { M.code1; M.code2; M.c.signal(); M.code3; } P2() { M.c.wait(); M.code4; M.code5; }
进程互斥 进程互斥是指多个进程在同一时刻只能有一个进程执行,其他进程必须等待。 互斥代码分为四个部分:
进入区:检查是否可以进入临界区,若可进入,需要“上锁”
临界区:进程执行的代码(访问临界资源的代码)
退出区:将进程从临界区中移除,“解锁”
剩余区:进程剩余的代码。
进程互斥需要遵守的原则 空闲让进:临界区空闲,应允许一个进程访问。 忙则等待:临界区被访问时,其他试图访问的进程需要等待。 有限等待:需要在有限的时间内进入临界区,保证不会饥饿。 让权等待:进程不能进入临界区时,应立即释放处理器,避免忙等待。
信号量机制实现互斥 信号量机制是一种用于进程互斥的机制,它可以用来控制进程的执行顺序。 以下是实现code1互斥:
1 2 3 4 5 6 7 semaphore mutex = 1 ; P1() { P(mutex); code1; V(mutex); }
其中P操作(wait)时S.value–,V操作(signal)时S.value++。
管程机制实现互斥 管程机制是一种用于进程互斥的机制,它可以用来控制进程的执行顺序。 以下是实现code1互斥:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 class monitor { condition c; void code1 () { c.wait(); code1; c.signal(); } } monitor M { condition c; code1; c.signal(); } P1() { M.c.wait(); M.code1; M.c.signal(); }
生产者-消费者问题 生产者生产数据,消费者消费数据。 生产者-消费者问题是一个经典的进程同步问题,它可以用来解决多进程之间的同步问题。
生产者 v —–full—-> p 消费者 生产者 p <—-empty—- v 消费者
互斥的P操作先执行会导致死锁,所以先执行同步的P操作。
代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 semaphore mutex = 1 ; semaphore empty = n; semaphore full = 0 ; Producer() { while (true ) { produce an item in nextp; P(empty); if (empty == 0 ) { } P(mutex); add the item to buffer; V(mutex); V(full); } } Consumer() { while (true ) { P(full); if (full < 0 ) { } P(mutex); remove an item from buffer; V(mutex); V(empty); consume the item; } }
读者-写者问题 读者-写者问题是一个经典的进程同步问题,它可以用来解决多进程之间的同步问题。 读-读 不互斥 写-其他 互斥 代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 semaphore rw = 1 ; int readcount = 0 ; semaphore mutex = 1 ; semaphore w = 1 ; Writer() { P(w); P(rw); Write(); V(rw); V(w); } Reader() { while (1 ) { P(w); P(mutex); if (readcount == 0 ) P(rw); readcount++; V(mutex); V(w); Read(); P(mutex); readcount--; if (readcount == 0 ) V(rw); V(mutex); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 #include <stdio.h> #include <string.h> #include <time.h> #include <stdlib.h> void func_A () { FILE *cpuinfo, *version; cpuinfo = fopen(“/proc/cpuinfo”, “r”); version = fopen(“/proc/version”, “r”); } void func_B () { } void func_C () { } void main (int argc, char *argv[]) { char c1,c2; if (argc==1 ) { func_A(); return ; } if (argc>1 ) { sscanf (argv[1 ],"%c%c" ,&c1,&c2); if (c1!=‘-’) return ; if (c2=='s' ) { func_B(); return ; } if (c2=='l' ) { if (argc<4 ) return ; Internal=atoi(argv[2 ]); duration=atoi(argv[3 ]); func_C(); return ; } } }