头文件: <semaphore.h>
/*****************************************************************************************
函数:信号量创建
原型:int sem_init(sem_t* sem, int pshared, unsigned int value);
形参列表
sem :信号量
pshared :[FALSE] 表示信号量sem用于线程间通信,且sem应当处于多线程可以共同访问的空间,
比如全局变量、在堆上动态分配的变量。
[TRUE]表示信号量用于进程间通信,且sem应处于共享内存或多进程可以共同访问的空
间,由父进程以fork()创建的子进程,如果它们拥有共同的内存空间,那么父子进程都
可以访问sem(任何可以访问同一共享内存的的进程都可以操控信号量。
value :sem的值
返回值
[0]表示创建成功
[-1]表示表示错误,并设置errno指示错误情况
示例:
sem_t semID; //全局变量
int ret = sem_init(&semID, 0, 2);
******************************************************************************************/
/*****************************************************************************************
函数:信号量等待
原型:①int sem_wait(sem_t* sem);
②int sem_trywait(sem_t* sem);
③int sem_timedwait(sem_t* sem, const struct timespec* abs_timeout);
形参列表
sem :信号量
abs_timeout :等待时间,sem_wait()是阻塞等待,sem_trywait()是非阻塞等待,
sem_timedwait()是定时等待。
返回值
所有这些函数在成功时返回0;在错误时,信号量的值保持不变,返回-1,且errno被设置以指示错误
******************************************************************************************/
/*****************************************************************************************
函数:发射(发送、抛出、释放)信号量
原型:int sem_post(sem_t* sem);
描述:Sem_post增加sem(unlocks)所指向的信号量。 如果信号量的值因此大于0,那么在sem_wait()调用中
阻塞的另一个进程或线程将被唤醒,并继续锁定信号量。
返回值
成功返回0,失败返回-1,且信号量的值保持不变,且errno被设置以指示错误
******************************************************************************************/
编译:添加 -lpthread 选项
示例:gcc -lpthread code.c -o a.out
/* 示例代码:创建两个线程访问同一个全局变量number */
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#include <semaphore.h>
#include <pthread.h>
#include <sys/types.h>
unsigned int number = 0;
void* thread1(void* para); //线程1服务函数
void* thread2(void* para); //线程2服务函数
int main(int argc, char** argv)
{
pthread_t threadID1, threadID2;
int ret = 0;
ret = pthread_create(&threadID1, NULL, thread1, NULL); //创建线程1
if(ret)
{
printf("Thread1 create failed!\n");
exit(EXIT_FAILURE);
}
ret = pthread_create(&threadID2, NULL, thread2, NULL); //创建线程2
if(ret)
{
printf("Thread2 create failed!\n");
exit(EXIT_FAILURE);
}
pthread_join(threadID1, NULL); //等待线程thread1结束
pthread_join(threadID2, NULL); //等待线程thread2结束
ptherad_exit((void*)0); //退出现场main
return 0;
}
void* thread1(void* para)
{
printf("Function thread1 running...\n");
while(1)
{
number = 100;
sleep(1);
printf("number: %u\n", number);
}
pthread_exit((void*)0);
}
void* thread2(void* para)
{
unsigned int count = 0;
printf("Function thread2 running...\n");
while(1)
{
count++;
number = count;
}
pthread_exit((void*)0);
}
结果分析:没有二元信号量的约束,线程thread1对number的赋值几乎不会等于100,原因是线程thread2对number的访问导致的。
/* 示例代码:创建两个线程访问同一个全局变量number,并加以信号量限制 */
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#include <semaphore.h>
#include <pthread.h>
#include <sys/types.h>
unsigned int number = 0;
sem_t semID;
void* thread1(void* para);
void* thread2(void* para);
int main(int argc, char** argv)
{
pthread_t threadID1, threadID2;
int ret = 0;
ret = pthread_create(&threadID1, NULL, thread1, NULL);
if(ret)
{
printf("Thread1 create failed!\n");
exit(EXIT_FAILURE);
}
ret = pthread_create(&threadID2, NULL, thread2, NULL);
if(ret)
{
printf("Thread2 create failed!\n");
exit(EXIT_FAILURE);
}
ret = sem_init(&semID, 0, 1);
if(ret == -1)
{
printf("Sem create failed!\n");
exit(EXIT_FAILURE);
}
pthread_join(threadID1, NULL);
pthread_join(threadID2, NULL);
ptherad_exit((void*)0);
return 0;
}
void* thread1(void* para)
{
printf("Function thread1 running...\n");
while(1)
{
sem_wait(&semID); //等待信号量
number = 100;
sleep(1);
printf("number: %u\n", number);
sem_post(&semID); //释放信号量
}
pthread_exit((void*)0);
}
void* thread2(void* para)
{
unsigned int count = 0;
printf("Function thread2 running...\n");
while(1)
{
sem_wait(&semID);
count++;
number = count;
sem_post(&semID);
}
pthread_exit((void*)0);
}
结果分析:加入信号量后,不管是线程thread1还是线程thread2对number的访问都不能同时进行,对全局变量number进行了很好的保护。