int pthread_attr_init(pthread_attr_t *attr)
int pthread_attr_setscope(pthread_attr_t *attr, int scope)
int pthread_attr_getscope(pthread_attr_t *tattr, int *scope)
int pthread_mutex_init(pthread_mutex_t *mutex,const pthread_mutex_attr_t *mutexattr);
int pthread_mutex_lock(pthread_mutex_t *mutex);
int pthread_mutex_unlock(pthread_mutex_t *mutex);
int pthread_mutex_destroy(pthread_mutex_t *mutex);
int pthread_cond_init(pthread_cond_t *cond,pthread_condattr_t *cond_attr);
int pthread_cond_wait(pthread_cond_t *cond,pthread_mutex_t *mutex);
int pthread_cond_timedwait(pthread_cond_t *cond,pthread_mutex_t *mutex,const timespec *abstime);
int pthread_cond_destroy(pthread_cond_t *cond);
int pthread_cond_signal(pthread_cond_t *cond);
int pthread_cond_broadcast(pthread_cond_t *cond); //解除所有线程的阻塞
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include"pthread.h"
#define BUFFER_SIZE 16
struct prodcons
{
int buffer[BUFFER_SIZE];
pthread_mutex_t lock; //mutex ensuring exclusive access to buffer
int readpos,writepos; //position for reading and writing
pthread_cond_t notempty; //signal when buffer is not empty
pthread_cond_t notfull; //signal when buffer is not full
};
//initialize a buffer
void init(struct prodcons* b)
{
pthread_mutex_init(&b->lock,NULL);
pthread_cond_init(&b->notempty,NULL);
pthread_cond_init(&b->notfull,NULL);
b->readpos=0;
b->writepos=0;
}
//store an integer in the buffer
void put(struct prodcons* b, int data)
{
pthread_mutex_lock(&b->lock);
//wait until buffer is not full
while((b->writepos+1)%BUFFER_SIZE==b->readpos)
{
printf("wait for not full\n");
pthread_cond_wait(&b->notfull,&b->lock);
}
b->buffer[b->writepos]=data;
b->writepos++;
pthread_cond_signal(&b->notempty); //signal buffer is not empty
pthread_mutex_unlock(&b->lock);
}
//read and remove an integer from the buffer
int get(struct prodcons* b)
{
int data;
pthread_mutex_lock(&b->lock);
//wait until buffer is not empty
while(b->writepos==b->readpos)
{
printf("wait for not empty\n");
pthread_cond_wait(&b->notempty,&b->lock);
}
data=b->buffer[b->readpos];
b->readpos++;
if(b->readpos>=BUFFER_SIZE) b->readpos=0;
pthread_cond_signal(&b->notfull); //signal buffer is not full
pthread_mutex_unlock(&b->lock);
return data;
}
#define OVER -1
struct prodcons buffer;
void * producer(void * data)
{
int n;
for(n=0;n<1000;++n)
{
printf("put-->%d\n",n);
put(&buffer,n);
}
put(&buffer,OVER);
printf("producer stopped\n");
return NULL;
}
void * consumer(void * data)
{
int n;
while(1)
{
int d=get(&buffer);
if(d==OVER) break;
printf("%d-->get\n",d);
}
printf("consumer stopped\n");
return NULL;
}
int main()
{
pthread_t tha,thb;
void * retval;
init(&buffer);
pthread_creare(&tha,NULL,producer,0);
pthread_creare(&thb,NULL,consumer,0);
pthread_join(tha,&retval);
pthread_join(thb,&retval);
return 0;
}
PS:如果遇到如下问题:加个编译条件'-pthread'
prodcons.c:(.text+0x2ab): undefined reference to `pthread_create'
prodcons.c:(.text+0x2bd): undefined reference to `pthread_join'
3)信号量
如同进程一样,线程也可以通过信号量来实现通信,虽然是轻量级的。
信号量函数的名字都以"sem_"打头。线程使用的基本信号量函数有四个。
#include <semaphore.h>
int sem_init(sem_t *sem , int pshared, unsigned int value);
这是对由sem指定的信号量进行初始化,设置好它的共享选项(linux只支持为0,即表示它是当前进程的局部信号量),然后给它一个初始值VALUE。
两个原子操作函数:
int sem_wait(sem_t *sem);
int sem_post(sem_t *sem);
这两个函数都要用一个由sem_init调用初始化的信号量对象的指针做参数。
sem_post:给信号量的值加1;
sem_wait:给信号量减1;对一个值为0的信号量调用sem_wait,这个函数将会等待直到有其它线程使它不再是0为止。
int sem_destroy(sem_t *sem);
这个函数的作用是再我们用完信号量后都它进行清理。归还自己占有的一切资源。
用信号量的方法实现生产者消费者
这里使用4个信号量,其中两个信号量occupied和empty分别用于解决生产者和消费者线程之间的同步问题,pmut和cmut是用于这两个线程之间的互斥问题。其中empty初始化为N(有界缓区的空间元数),occupied初始化为0,pmut和cmut初始化为1。