大家都知道互斥量可以用于线程间的同步,但是一次只能有一个线程抢到互斥量,限制了程序的并发释放。如果我们要让多个线程同时访问同一个资源,就没有办法使用互斥锁了。只有互斥锁会锁住整个共享资源,只允许一个线程访问它。这种现象使得线程轮流运行,即线程从并行执行变为串行执行,这与直接使用单进程没有区别。因此,Linux系统提出了信号量的概念。这是一种比较折衷的处理方式,既能保证线程间的同步,数据不会混淆,又能提高线程的并发性。注意,这里说的信号量与我们学过的信号无关,就像Java与JavaScript无关一样。主要应用函数:sem_init函数sem_destroy函数sem_wait函数sem_trywait函数sem_timedwait函数sem_post函数以上六个函数的返回值分别为:成功返回0,失败返回-1,同时设置errno。细心的读者可能会注意到,它们没有pthread前缀,这意味着信号量不仅可以在线程之间使用,还可以在进程之间使用。sem_t数据类型本质上还是一个结构体。但是就像文件描述符一样,我们可以在应用过程中将其简单地视为一个整数,而忽略实现细节。用法:sem_tsem;我们约定信号量sem不能小于0,使用时注意包含头文件。与互斥量类似,信号量也有类似加锁和解锁的操作。sem_wait函数用于加锁,sem_post函数用于解锁。这两个函数有以下特点:调用sem_post时,如果信号量大于0,则信号量减一;当信号量等于0时,线程在调用sem_post时会被阻塞;唤醒阻塞在信号量上的线程。由于上述线程的加减法对用户隐藏了sem_t的实现,所以这两个操作只能通过函数实现,不能直接使用++和--符号进行操作。##sem_init函数原型:intsem_init(sem_t*sem,intpshared,unsignedintvalue);功能:初始化一个信号量;参数说明:sem:信号量;pshared:设置为0时,信号量用于线程间同步;当非零(通常为1)时,用于进程间同步;value:指定信号量的初值,信号量的初值决定了允许同时占用信号量的线程数。##sem_destroy函数函数原型:intsem_destroy(sem_t*sem);函数功能:销毁一个信号量##sem_wait函数函数原型:intsem_wait(sem_t*sem);函数功能:信号量值加一##sem_post函数函数原型:intsem_post(sem_t*sem);函数功能:信号量值减一##sem_trywait函数函数原型:intsem_trywait(sem_t*sem);函数功能:尝试锁定信号量,类似pthread_mutex_trylock;##sem_timedwait函数原型:intsem_timedwait(sem_tsem,conststructtimespecabs_timeout);功能:限时尝试锁定信号量参数说明:sem:semaphore;abs_timeout:同pthread_cond_timedwait,使用绝对时间。用法如下(例如设置超时为1秒):time_tcur=time(NULL);获取当前时间。结构timespect;定义timespec结构体变量tt.tv_sec=cur+1;计时1秒t.tv_nsec=t.tv_sec+100;sem_timedwait(&sem,&t);传参生产者消费者信号量模型:/*Semaphore实现生产者消费者问题*/#include
