//深入理解计算机系统
1,信号量s是具有非负整数值的全局变量,只能由两种特殊的操作来处理,这两种操作称为P和V:
P(s):如果s是非零的,那么P将s减1,并且立即返回。如果s为零,那么就挂起这个线程,直到s变为非零,而一个V操作会重启这个线程。在重启止呕,P操作将s减1,并将控制返回给调用者。
V(s):V操作将s加1。如果有任何线程阻塞在P操作等待s变成非零,那么V操作会重启这些线程中的一个,然后该线程将s减1,完成它的P操作。(V的定义中没有定义等待线程被重新启动的顺序。唯一的要求是V必须只能重启一个正在等待的线程。因此,当有多个线程在等待同一个信号量时,你不能预测V操作要重启哪个线程。)
The definitions of P and V ensure that a running program can never enter a state where a properly initialized semaphore has a negative value.
2,生产者-消费者问题
1,信号量s是具有非负整数值的全局变量,只能由两种特殊的操作来处理,这两种操作称为P和V:
P(s):如果s是非零的,那么P将s减1,并且立即返回。如果s为零,那么就挂起这个线程,直到s变为非零,而一个V操作会重启这个线程。在重启止呕,P操作将s减1,并将控制返回给调用者。
V(s):V操作将s加1。如果有任何线程阻塞在P操作等待s变成非零,那么V操作会重启这些线程中的一个,然后该线程将s减1,完成它的P操作。(V的定义中没有定义等待线程被重新启动的顺序。唯一的要求是V必须只能重启一个正在等待的线程。因此,当有多个线程在等待同一个信号量时,你不能预测V操作要重启哪个线程。)
The definitions of P and V ensure that a running program can never enter a state where a properly initialized semaphore has a negative value.
2,生产者-消费者问题
点击(此处)折叠或打开
- typedef struct sbuf_t
- {
- int *buf;//Buffer array.
- int n;//Buffer的大小,即最大slots个数。
- int fornt;
- int rear;
- sem_t mutex;//提供互斥的buf访问。
- sem_t slots;//可用的空槽位的数量。
- sem_t items;//可用项目的数量。
- }sbuf_t;
- //sbuf_init函数为缓冲区分配堆存储器。
- void sbuf_init(sbuf_t *sp,int n)
- {
- sp->buf=calloc(n,sizeof(int));//即sp->buf=(int *)malloc(n*sizeof(int));
- sp->n=n;
- sp->front=sp->rear=0;
- sem_init(&sp->mutex,0,1);
- sem_init(&sp->slots,0,n);
- sem_init(&sp->items,0,0);
- return ;
- }
- //生产者
- //sbuf_insert函数等待一个可用的槽位,对互斥锁加锁,添加项目,对互斥锁解锁,然后宣布一个新项目可用。
- //sem_wait,sem_post分别对应与P,V操作。
- void sbuf_insert(sbuf_t *sp,int item)
- {
- sem_wait(&sp->slots);
- sem_wait(&sp->mutex);
- //以上两个wait函数不能互换,以防死锁。
- sp->buf[(++sp->rear)%(sp->n)]=item;
- sem_post(&sp->mutex);
- sem_post(&sp->items);
- }
- //消费者
- int sbuf_remove(sbuf_t* sp)
- {
- int item;
- sem_wait(&sp->items);
- sem_wait(&sp->mutex);
- item=sp->buf[(++sp->front)%(sp->n)];
- sem_post(&sp->mutex);
- sem_post(&sp->slots);
- return item;
- }