Linux 实现了POSIX 的无名信号量,主要用于线程间的互斥同步。这里主要介绍几个常见函数。
· sem_init用于创建一个信号量,并能初始化它的值。
· sem_wait和sem_trywait相当于P操作,它们都能将信号量的值减一,两者的区别在 于若信号量小于零时,sem_wait将会阻塞进程,而 sem_trywait则会立即返回。
· sem_post相当于V操作,它将信号量的值加一同时发出信号唤醒等待的进程。
· sem_getvalue用于得到信号量的值。
· sem_destroy用于删除信号量。
所需头文件 #include <semaphore.h>
函数原型 int sem_init(sem_t *sem,int pshared,unsigned int value)
sem:信号量
pshared:决定信号量能否在几个进程间共享。由于目前Linux还没有实现进程间共享信号量,所以这个值只能够取0
value:信号量初始化值
函数返回值 成功:0 ,出错:-1
#include <semaphore.h>
函数原型
int sem_wait(sem_t *sem)
int sem_trywait(sem_t *sem)
int sem_post(sem_t *sem)
int sem_getvalue(sem_t *sem)
int sem_destroy(sem_t *sem)
函数传入值 sem:信号量
函数返回值 成功:0 ,出错:-1
从上面函数来看,实现线程之间同步信号量比互斥锁使用起来相对容易一些,操作简单,容易理解,适用范围广。
#include <stdio.h>
#include <semaphore.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
int g_Flag = 0;
sem_t sem_mutex; // 用于互斥
sem_t sem_syn; // 用于同步
void *thread1( void *arg );
void *thread2( void *arg );
int main()
{
pthread_t tid1, tid2;
int rc1, rc2;
sem_init( &sem_mutex, 0, 1 );
sem_init( &sem_syn, 0, 0 );
printf( " Inter main !\n" );
rc2 = pthread_create( &tid2, NULL, thread2, NULL);
if( rc2 != 0 )
{
printf( " %s, %d \n", __func__, strerror( rc2 ) );
}
rc1 = pthread_create( &tid1, NULL, thread1, &tid2 );
if( rc1 != 0 )
{
printf( " %s, %d \n", __func__, strerror(rc1) );
}
sem_wait( &sem_syn ); // 同步等待,阻塞
printf( " Leave main!\n\n" );
return 0;
}
void *thread1( void *arg )
{
pthread_t *ptid = NULL;
printf( " Enter thread1\n" );
printf( " thread1 id: %u, g_Flag: %d \n", ( unsigned int )pthread_self(), g_Flag );
if( sem_wait( &sem_mutex ) != 0)
{
perror(" pthread1 sem_mutex\n");
}
if( g_Flag == 2 )
{
sem_post( &sem_syn);
}
g_Flag = 1;
if( sem_post( &sem_mutex ) != 0)
{
perror( "pthread1 sem_post\n" );
}
printf( " thread1 id: %u, g_Flag: %d \n",( unsigned int )pthread_self(), g_Flag );
printf( "Leave thread1 \n\n" );
ptid = ( pthread_t *)arg;
printf( " ptid = %u \n", *ptid );
pthread_join( *ptid, NULL );
pthread_exit(0 );
}
void *thread2( void *arg )
{
printf( " Enter thread2 !\n" );
printf( " thread2 id: %u , g_Flag: %d \n", ( unsigned int)pthread_self(), g_Flag );
if( sem_wait( &sem_mutex ) != 0 )
{
perror( "thread2 sem_wait \n" );
}
if( g_Flag == 1 )
{
sem_post( &sem_syn );
}
g_Flag = 2;
if( sem_post( &sem_mutex ) != 0)
{
perror( " thread2 sem_post\n" );
}
printf( " thread2 id: %u , g_Flag: %d \n", ( unsigned int )pthread_self(), g_Flag );
printf( "Leave thread2 \n\n" );
pthread_exit(0);
}
运行结果:
Inter main !
Enter thread2 !
thread2 id: 3086269328 , g_Flag: 0
thread2 id: 3086269328 , g_Flag: 2
Leave thread2
Enter thread1
thread1 id: 3075779472, g_Flag: 2
thread1 id: 3075779472, g_Flag: 1
Leave thread1
ptid = 3086269328
Leave main!