信号量
信号量本质上是一个的整数计数器, 它被用来控制对公共资源的访问. 当公共资源增加时, 调用 函数sem_post()增加信号量. 只有当信号量值大于0时, 才能使用公共资源, 使用后函数sem_wait()减少信号量. 函数sem_trywait() 和函数 pthread_mutex_trylock() 起同样的作用, 它是函数sem_wait()的非阻塞版本.
它们在头文件/usr/include/semaphore.h中.
信号量的数据类型的结构是sem_t, 它本质是一个长整形的数. 函数sem_init()用来初始化一个信号量. 它的原型为: extern int sem_init __P(( sem_t * __sem, int __pshared, unsigned int __value));
sem为指向信号结构的一个指针; pshared不为0时此信号在进程间共享, 否则只能为当前进程所有线程共享; value给出了信号量的初始值.
函数sem_post( sem_t * sem)用来增加信号量的值. 当有线程阻塞在这个信号量上时, 调用这个函数会使其中的一个线程不再阻塞, 选择机制同样是线程的调度策略决定的.
函数sem_wait( sem_t * sem)被用来阻塞当前线程直到信号量sem的值大于0, 解除阻塞后将sem的值减一, 表明公共资源已经使用后减少.
函数sem_trywait( sem_t * sem)是函数sem_wait的非阻塞版本, 它直接将信号量sem的值减一.
函数sem_destroy(sem_t * sem)用来释放信号量sem.
来看一个例子, 一共有4个线程, 其中两个线程负责从文件读取数据到公共缓冲区, 另两个线程从缓冲区读取数据作不同的处理( 加和乘运算)
/*file sem.c */
#include<stdio.h>
#include<pthread.h>
#include<semaphore.h>
#define MAXSTACK 100
int stack[MAXSTACK][2];
int size = 0;
sem_t sem;
/*从文件1.dat读取数据, 每读一次信号量加一*/
void ReadData1(void)
{
FILE *fp = fopen( "1.dat", "r");
while( !feof(fp))
{
fscanf( fp,"%d %d", &stack[size][0], &stack[size][1]);
sem_post( &sem);
++size;
}
fclose( fp);
}
/*从文件2.dat读取数据*/
void ReadData2( void)
{
FILE *fp = fopen("2.dat", "r");
while( !feof( fp))
{
fscanf( fp, "%d %d", &stack[size][0], &stack[size][1]);
sem_post( &sem);
++size;
}
}
/*阻塞等待缓冲区有数据, 读取数据后, 释放空间,继续等待*/
void HandleData1(void)
{
while(1)
{
sem_wait(&sem);
printf(Plus: %d + %d = %d\n", stack[size][0], stack[size][1]), stack[size][0] +stack[size][1]);
--size;
}
}
void HandleData2(void)
{
while(1)
{
sem_wait( &sem);
printf("Multiply: %d * %d = %d\n", stack[size][0], stack[size][1], stack[size][0]*stack[size][1]);
--size;
}
}
int main(void)
{
pthread_t t1,t2,t3,t4;
sem_init(&sem, 0, 0);
pthread_create( &t1, NULL, (void*)HandleData1, NULL);
pthread_create( &t2, NULL, (void*)HandleData2, NULL);
pthread_create( &t3, NULL, (void*)ReadData1, NULL);
pthread_create( &t4, NULL, (void*)ReadData2, NULL);
pthread_join( t1, NULL);
}
信号量本质上是一个的整数计数器, 它被用来控制对公共资源的访问. 当公共资源增加时, 调用 函数sem_post()增加信号量. 只有当信号量值大于0时, 才能使用公共资源, 使用后函数sem_wait()减少信号量. 函数sem_trywait() 和函数 pthread_mutex_trylock() 起同样的作用, 它是函数sem_wait()的非阻塞版本.
它们在头文件/usr/include/semaphore.h中.
信号量的数据类型的结构是sem_t, 它本质是一个长整形的数. 函数sem_init()用来初始化一个信号量. 它的原型为: extern int sem_init __P(( sem_t * __sem, int __pshared, unsigned int __value));
sem为指向信号结构的一个指针; pshared不为0时此信号在进程间共享, 否则只能为当前进程所有线程共享; value给出了信号量的初始值.
函数sem_post( sem_t * sem)用来增加信号量的值. 当有线程阻塞在这个信号量上时, 调用这个函数会使其中的一个线程不再阻塞, 选择机制同样是线程的调度策略决定的.
函数sem_wait( sem_t * sem)被用来阻塞当前线程直到信号量sem的值大于0, 解除阻塞后将sem的值减一, 表明公共资源已经使用后减少.
函数sem_trywait( sem_t * sem)是函数sem_wait的非阻塞版本, 它直接将信号量sem的值减一.
函数sem_destroy(sem_t * sem)用来释放信号量sem.
来看一个例子, 一共有4个线程, 其中两个线程负责从文件读取数据到公共缓冲区, 另两个线程从缓冲区读取数据作不同的处理( 加和乘运算)
/*file sem.c */
#include<stdio.h>
#include<pthread.h>
#include<semaphore.h>
#define MAXSTACK 100
int stack[MAXSTACK][2];
int size = 0;
sem_t sem;
/*从文件1.dat读取数据, 每读一次信号量加一*/
void ReadData1(void)
{
FILE *fp = fopen( "1.dat", "r");
while( !feof(fp))
{
fscanf( fp,"%d %d", &stack[size][0], &stack[size][1]);
sem_post( &sem);
++size;
}
fclose( fp);
}
/*从文件2.dat读取数据*/
void ReadData2( void)
{
FILE *fp = fopen("2.dat", "r");
while( !feof( fp))
{
fscanf( fp, "%d %d", &stack[size][0], &stack[size][1]);
sem_post( &sem);
++size;
}
}
/*阻塞等待缓冲区有数据, 读取数据后, 释放空间,继续等待*/
void HandleData1(void)
{
while(1)
{
sem_wait(&sem);
printf(Plus: %d + %d = %d\n", stack[size][0], stack[size][1]), stack[size][0] +stack[size][1]);
--size;
}
}
void HandleData2(void)
{
while(1)
{
sem_wait( &sem);
printf("Multiply: %d * %d = %d\n", stack[size][0], stack[size][1], stack[size][0]*stack[size][1]);
--size;
}
}
int main(void)
{
pthread_t t1,t2,t3,t4;
sem_init(&sem, 0, 0);
pthread_create( &t1, NULL, (void*)HandleData1, NULL);
pthread_create( &t2, NULL, (void*)HandleData2, NULL);
pthread_create( &t3, NULL, (void*)ReadData1, NULL);
pthread_create( &t4, NULL, (void*)ReadData2, NULL);
pthread_join( t1, NULL);
}