信号量相当于进化版的互斥锁。由于互斥锁的粒度比较大,如果我们希望在多个线程间对某一对象的部分数据进行共享,使用互斥锁是没有办法实现的,只能将整个数据对象锁住。这样虽然达到了多线程操作共享数据时保证数据正确性的目的,却无形中导致线程的并发性下降,线程从并行执行变成了串行执行,与直接使用单进程无异。信号量是相对折衷的一种处理方式,既能保证同步,数据不混乱,又能提高线程并发。
可以这么理解,比如说现在有一个资源可以允许三个线程同时访问,如果用互斥量的话,当第一个线程获取互斥锁的时候,后面的线程都会阻塞,这就无法实现三个线程同时访问资源了,会大大降低资源的利用效率。如果使用信号量,那个给信号量一个初值,每有一个线程访问到资源,信号量就减一,当减到0的时候,说明已经满足最多同时访问的线程数量了,后面的线程就不能再访问资源了,会阻塞。
#include <semaphore.h>
int sem_init(sem_t *sem, int pshared, unsigned int value);
Link with -lrt or -pthread.
#include <semaphore.h>
int sem_destroy(sem_t *sem);
Link with -lrt or -pthread.
#include <semaphore.h>
/*--操作*/
int sem_wait(sem_t *sem);
int sem_trywait(sem_t *sem);
int sem_timedwait(sem_t *sem, const struct timespec *abs_timeout);
Link with -lrt or -pthread.
#include <semaphore.h>
/*++操作*/
int sem_post(sem_t *sem);
Link with -lrt or -pthread.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <semaphore.h>
#define MAX 6
sem_t blank, ful;
int vector[MAX];
int gdata = 100;
void* producer_th(void* arg)
{
int i = 0;
while(1)
{
sem_wait(&blank);
printf("thread: %s, tid: %lu, data: %d\n", __FUNCTION__,\
pthread_self(), gdata);
vector[(i++)%MAX] = gdata++;
sem_post(&ful);
sleep(rand()%3);
}
return NULL;
}
void* consumer_th(void* arg)
{
int i = 0;
int num = 0;
while(1)
{
sem_wait(&ful);
num = vector[(i++) % MAX];
printf("thread: %s, tid: %lu, data: %d\n", __FUNCTION__,\
pthread_self(), num);
sem_post(&blank);
sleep(rand()%3);
}
return NULL;
}
int main(int argc, char* argv[])
{
sem_init(&blank, 0, MAX); /*生产者*/
sem_init(&ful, 0, 0); /*消费者*/
pthread_t t1, t2;
pthread_create(&t1, NULL, producer_th, NULL);
pthread_create(&t2, NULL, consumer_th, NULL);
pthread_join(t1, NULL);
pthread_join(t2, NULL);
sem_destroy(&blank);
sem_destroy(&ful);
return 0;
}