概念:
临界区**指的是一个访问共用资源(例如:共用设备或是共用存储器)的程序片段,而这些共用资源又无法同时被多个线程访问的特性。
临界区调度原则:
1、如果有若干进程要求进入空闲的临界区,一次仅允许一个进程进入。
2、任何时候,处于临界区内的进程不可多于一个。如已有进程进入自己的临界区,则其它所有试图进入临界区的进程必须等待。
3、进入临界区的进程要在有限时间内退出,以便其它进程能及时进入自己的临界区。
4、如果进程不能进入自己的临界区,则应让出CPU,避免进程出现“忙等”现象。
信号量(semaphore): 可用于进程间同步也可用于同一个进程间的线程同步。
信号量有一个使用计数器,这个使用计数器,是信号量的最大资源计数和当前资源计数的差值。
计数器的值大于0时,表示当前可用资源个数。
计数器的值小于0时,表等待使用资源的进程个数。
计数器的值为0则既没有可用资源也没有等待资源的进程
假设S的为信号量的计数器的值:
P操作:执行一次P操作意味着请求分配一个单位的资源,因此S的值减1,当S<0时,表示已经没有可用资源,请求者必须等待别的进程释放该类资源,它才能继续运行。
V操作:执行一次V操作意味着释放一个资源,因此S的值加1,当S<0,表示有某些进程正在等待资源,因此要唤醒一个等待状态的进程,使之继续运行。
模型一:(放黑白棋子)
#include <stdio.h> #include <string.h> #include <stdlib.h> #include <unistd.h> #include <pthread.h> #include<semaphore.h> #define P sem_wait #define V sem_post #define full &full_real #define empty &empty_real sem_t full_real; sem_t empty_real; int num=0; //P1 void* P1() { while(num<50) { P(full); num++; printf("拣起白子%d ",num); V(empty); } } //P2 void* P2() { while(num<50) { P(empty); num++; printf("拣起黑子%d ",num); V(full); } } int main() { sem_init(full, 0, 0); sem_init(empty, 0, 1); pthread_t tid0; pthread_t tid1; pthread_t tid2; pthread_create(&tid0, NULL, P1, NULL); pthread_create(&tid2, NULL, P1, NULL); pthread_create(&tid1, NULL, P2, NULL); pthread_exit(0); }
运行结果:
拣起黑子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 拣起白子48 拣起黑子49 拣起白子50 拣起黑子51 拣起白子52 -------------------------------- Process exited after 2.032 seconds with return value 52 请按任意键继续. . .