线程同步需要两种机制,分别是互斥锁和条件变量
一:::::互斥锁
互斥锁的初始化
pthread_mutex_init(pthread_mutex_t *mutex,const pthread-mutex_attr *attr)
mutex初始化
attr为互斥锁的属性
释放互斥锁
pthread_mutex_destory(pthread_mutex_t *mutex);
阻塞型互斥锁上锁
int phread_mutex_lock(pthread _mutex_t *mutex);
如果mutex已经被锁定,那么当前调用的线程阻塞到互斥锁被其他线程释放;
非阻塞型互斥锁上锁
int pthread_mutex_trylock(pthread_mutex_t*mutex);
如果mutex已经被锁定,那么调用该函数时直接返回;
互斥锁解锁
int pthread_mutex_unlock(pthread_mutex_t*mutex);
如果pthread_mutex_unlock执行成功,返回0,其他值失败;
#include <stddef.h>
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
char buffer[256];
int retflag = 0;
pthread_mutex_t mutex;
int i = 0;
void one();
void two();
int main()
{
pthread_t reader1,reader2;
pthread_mutex_init(&mutex,NULL);
pthread_create(&reader1, NULL, (void*)(&one), NULL);
pthread_create(&reader2, NULL, (void*)(&two), NULL);
pthread_join(reader1,NULL);
pthread_join(reader2,NULL);
return 0;
}
void one()
{
while(1)
{
pthread_mutex_lock(&mutex);
i++;
printf("one %d\n",i);
pthread_mutex_unlock(&mutex);
usleep(100000);
}
}
void two()
{
while(1)
{
pthread_mutex_lock(&mutex);
i++;
printf("two %d\n",i);
pthread_mutex_unlock(&mutex);
usleep(100000);
}
}
程序遇到
pthread_mutex_lock(&mutex);判断mutex状态,如未上锁则 上锁并运行一下程序,如已经上锁则等待;
二:::::条件变量
条件变量初始化
int phread_cond_init(phread_cond_t *cond, const pthread_cond_attr *attr);
cond初始化
attr为条件变量的属性
释放条件变量
int pthread_cond_destory(pthread_cond_t *cond);
阻塞条件变量
pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex);
时间设阻塞条件变量
pthread_cond_timewait(pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *abstime);
#include <stdio.h>
#include <pthread.h>
struct producers
{
int buffer[4];
pthread_mutex_t lock;
int readpos, writepos;
pthread_cond_t notempty;
pthread_cond_t notfull;
};
void init(struct producers *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;
}
void put(struct producers *b, int data)
{
pthread_mutex_lock(&b->lock);
while((b->writepos+1)%4==b->readpos)
{
pthread_cond_wait(&b->notfull,&b->lock);
}
b->buffer[b->writepos]=data;
b->writepos++;
if(b->writepos>=4) b->writepos=0;
pthread_cond_signal(&b->notempty);
pthread_mutex_unlock(&b->lock);
}
int get(struct producers *b)
{
int data;
pthread_mutex_lock(&b->lock);
while(b->writepos==b->readpos)
{
pthread_cond_wait(&b->notempty,&b->lock);
}
data=b->buffer[b->readpos];
b->readpos++;
if(b->readpos>=4) b->readpos=0;
pthread_cond_signal(&b->notfull);
pthread_mutex_unlock(&b->lock);
return data;
}
struct producers buffer;
void *producer(void *data)
{
int n;
for(n=0;n<10;n++)
{
printf("Producer : %d-->\n",n);
put(&buffer,n);
}
put(&buffer,-1);
return NULL;
}
void *consumer(void *data)
{
int d;
while(1)
{
d=get(&buffer);
if(d==-1) break;
printf("Consumer: --> %d\n",d);
}
return NULL;
}
int main()
{
pthread_t tha,thb;
void *retval;
init(&buffer);
pthread_create(&tha,NULL,producer,0);
pthread_create(&thb,NULL,consumer,0);
pthread_join(tha,&retval);
pthread_join(thb,&retval);
return 0;
}
运行效果
Producer : 0-->
Producer : 1-->
Producer : 2-->
Producer : 3-->
Consumer: --> 0
Consumer: --> 1
Consumer: --> 2
Producer : 4-->
Producer : 5-->
Producer : 6-->
Consumer: --> 3
Consumer: --> 4
Consumer: --> 5
Producer : 7-->
Producer : 8-->
Producer : 9-->
Consumer: --> 6
Consumer: --> 7
Consumer: --> 8
Consumer: --> 9
两个线程同时运行:
都在put和get中说明使用
举例:thb线程先运行遇到pthread_mutex_lock(&b->lock);上锁后接着运行一下程序,
而线程tha堵塞在pthread_mutex_lock(&b->lock);
thb线程接着遇到while(b->writepos==b->readpos)符合条件
运行pthread_cond_wait(&b->notempty,&b->lock);为&b->lock解锁自己阻塞等待唤醒;
线程tha在接到&b->lock解锁后运行一下面程序;
运行到pthread_cond_signal(&b->notempty)后唤醒线程thb;然而此时&b->lock未解锁thb无法运行;
直到线程tha符合while((b->writepos+1)%4==b->readpos)条件,
运行pthread_cond_wait(&b->notfull,&b->lock);为&b->lock解锁自己阻塞等待唤醒;
这样可以运行线程thb
以此循环。。。。。。。。
使用信号量同步线程
#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>
struct producers
{
int buffer[4];
int readpos, writepos;
sem_t sem_read;
sem_t sem_write;
};
void init(struct producers *b)
{
sem_init(&b->sem_write,0,3);
sem_init(&b->sem_read,0,0);
b->readpos=0;
b->writepos=0;
}
void put(struct producers *b, int data)
{
sem_wait(&b->sem_write);
b->buffer[b->writepos]=data;
b->writepos++;
if(b->writepos>=4) b->writepos=0;
sem_post(&b->sem_read);
}
int get(struct producers *b)
{
int data;
sem_wait(&b->sem_read);
data=b->buffer[b->readpos];
b->readpos++;
if(b->readpos>=4) b->readpos=0;
sem_post(&b->sem_write);
return data;
}
struct producers buffer;
void *producer(void *data)
{
int n;
for(n=0;n<10;n++)
{
printf("Producer : %d-->\n",n);
put(&buffer,n);
}
put(&buffer,-1);
return NULL;
}
void *consumer(void *data)
{
int d;
while(1)
{
d=get(&buffer);
if(d==-1) break;
printf("Consumer: --> %d\n",d);
}
return NULL;
}
int main()
{
pthread_t tha,thb;
void *retval;
init(&buffer);
pthread_create(&tha,NULL,producer,0);
pthread_create(&thb,NULL,consumer,0);
pthread_join(tha,&retval);
pthread_join(thb,&retval);
return 0;
}