同一个进程中不同线程之间的同步可以使用 POSIX Semaphores(其定义在semaphore.h),这个信号量要比进程间通信使用的信号量的结构简单,注意两者是不同的事物。
创建信号量对象:
sem_t sem_name;
很简单的一个变量,其中的sem_t类型也非常简单,下面是其类型定义:
typedef volatile unsigned char atomic_t
typedef atomic_t sem_t
初始化信号量:
int
sem_init(sem_t *sem, int pshared, unsigned int value);
参数一:是指向信号量对象的指针
参数二:表明该信号量是否在父子进程之间共享(Linux目前是不支持的)
参数三:要信号量设定的初始值。
查询信号量:
int
sem_getvalue(sem_t *sem, int *valp);
查询当前信号量的值,其值会以参数的形式返回到valp上。
P操作,索取信号量:
int
sem_wait(sem_t *sem);
参数是:是指向信号量的指针。
若信号量的值为0,则线程阻塞。否则信号量的值-1。
V操作,释放信号量:
int
sem_post(sem_t *sem);
参数:是指向信号量的指针。
信号量的值会+1,并且会唤醒某一个阻塞中的线程。
删除信号量:
int
sem_destroy(sem_t *sem);
参数:是指向信号量的指针。
注意删除信号量时不应该存在阻塞在该信号量上的线程,否则无法删除。
上面说的主要是针对Linux,而在Mac OSX下,并不支持sem_init()对信号量的建立,而是用sem_open()。
下面的测试程序(运行在Mac OSX)中,注释部分是适用于linux的。
#include <pthread.h>
#include <semaphore.h>
#include <stdio.h>
#include <stdlib.h>
#define NITER 1000000
int count = 0; //两个线程共享同一个资源:count
sem_t sem_for_linux;
sem_t *s;
void * ThreadAdd(void * a)
{
int i, tmp;
for(i = 0; i < NITER; i++)
{
sem_wait(s);
//sem_wait(&sem_for_linux);
//++count; //把自增的过程放大给你看
tmp = count; /* copy the global count locally */
tmp = tmp+1; /* increment the local copy */
count = tmp; /* store the local value into the global count */
sem_post(s);
//sem_post(&sem_for_linux);
}
return NULL;
}
int main(int argc, char * argv[])
{
pthread_t tid1, tid2;
sem_unlink("s");
s = sem_open("s", O_CREAT, 0, 1);;
//sem_init(&sem_for_linux, 0, 1);
// 创建两个线程
if(pthread_create(&tid1, NULL, ThreadAdd, NULL))
{
printf("\n ERROR creating thread 1");
exit(1);
}
if(pthread_create(&tid2, NULL, ThreadAdd, NULL))
{
printf("\n ERROR creating thread 2");
exit(1);
}
// 等待两个线程都结束
if(pthread_join(tid1, NULL)) /* wait for the thread 1 to finish */
{
printf("\n ERROR joining thread");
exit(1);
}
if(pthread_join(tid2, NULL)) /* wait for the thread 2 to finish */
{
printf("\n ERROR joining thread");
exit(1);
}
if (count < 2 * NITER)
printf("\n BOOM! count is [%d], should be %d\n", count, 2*NITER);
else
printf("\n OK! count is [%d]\n", count);
//sem_destroy(&sem_for_liux);
sem_destroy(s);
pthread_exit(NULL);
}