您的位置:首页 > 其它

多线程中互斥量与条件变量的使用

2011-05-18 11:15 369 查看
多线程中利用互斥量与条件变量进行线程间同步的过程如下:
1.线程入口处先get locker
2.判断条件变量的值
3条件变量为真进行相应的出来
4条件变量为假,调用pthread_cond_wait释放锁,并拥塞线程,此时执行流转到另一线程判断条件变量的真假。
5进行相应的处理之后,再次判读是否有必要更改条件变量的状态
6释放互斥锁
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#define MUTEX_COND_DEBUG
#ifdef MUTEX_COND_DEBUG
#define DB(x) x
#else
#define DB(x)
#endif
#define BUFFER_SIZE 8
struct Products
{
int buffer[BUFFER_SIZE];
pthread_mutex_t locker;          //保证存取操作的互斥性
pthread_cond_t notEmpty; //是否可读
pthread_cond_t notFull;          //是否可写
int posReadFrom;            	 //消费
int posWriteTo;             //生产
};
int BufferIsFull(struct Products* products)
{
if ((products->posWriteTo + 1) % BUFFER_SIZE == products->posReadFrom)
{
return (1);
}
return (0);
}
int BufferIsEmpty(struct Products* products)
{
if (products->posWriteTo == products->posReadFrom)
{
return (1);
}
return (0);
}
//制造产品
void Produce(struct Products* products, int item)
{
int empty;
//原子操作! 错!! 应该是得不到锁,进入阻塞状态,等待其他线程释放该锁。
pthread_mutex_lock(&products->locker);
DB(printf("Produce get the locker/n");)
//释放锁,这样消费线程才可以访问资源,并消费,之后通知notfull消息
while (BufferIsFull(products))
{
DB(printf("buffer is full, can not produce/n");)
DB(printf("Produce release the locker/n");)
/*如果条件不真,解互斥量锁,拥塞线程,知道条件为真,等条件为真时,再次将互斥量锁住*/
pthread_cond_wait(&products->notFull, &products->locker);
DB(printf("notFull is true and it will write/n");)
} //无空间可写入

//判断是否为空,设置empty标志
empty = BufferIsEmpty( products);
//写入数据
products->buffer[products->posWriteTo] = item;
DB(printf("done! producer: %d/n", item);)
products->posWriteTo++;
if (products->posWriteTo >= BUFFER_SIZE)
products->posWriteTo = 0;
//如果之前为空,则发通知给消费线程,新数据被写入,可以消费
if(empty)
{
DB(printf("buffer is empty,can not consume/n");)
DB(printf("buffer is writed,consume it/n");)
pthread_cond_signal(&products->notEmpty);
}
pthread_mutex_unlock(&products->locker);    //解锁
DB(printf("produce release the locker/n");)
}
//消费产品
int Consume(struct Products* products)
{
int item, full;
pthread_mutex_lock(&products->locker);
DB(printf("Consume get the locker/n");)
// 为空时持续等待,无数据可读,
// 进入等待状态,不占用CPU,同时,释放占用的互斥锁,一旦被唤醒则再次锁定互斥量,即锁定product结构体的读写。
while (BufferIsEmpty(products))
{
DB(printf("buffer is empty, can not consume/n");)
DB(printf("Consume release the locker/n");)
pthread_cond_wait(&products->notEmpty, &products->locker);
DB(printf("notEmpty is true and it will read/n");)
}
//判断是否为满,设置full标志
full = BufferIsFull(products);
//提取数据
item = products->buffer[products->posReadFrom];
DB(printf("done! consume: %d/n", item);)
products->posReadFrom++;
if (products->posReadFrom >= BUFFER_SIZE) //如果到末尾,从头读取
products->posReadFrom = 0;
//如果之前是full的,则发信号通知生产线程
if(full)
{
DB(printf("buffer is full,can not produce/n");)
DB(printf("buffer is consume, produce it/n");)
pthread_cond_signal(&products->notFull);
}
pthread_mutex_unlock(&products->locker);
DB(printf("consume release the locker/n");)
return item;
}
#define END_FLAG (-1)
struct Products products;
void* ProducerThread(void* data)
{
int i;
for (i = 0; i < 16; ++i)
{
printf("producer: %d/n", i);
Produce(&products, i);
}
Produce(&products, END_FLAG);
return NULL;
}
void* ConsumerThread(void* data)
{
int item;
while (1)
{
item = Consume(&products);
if (END_FLAG == item)
break;
printf("consumer: %d/n", item);
}
return (NULL);
}
int main(int argc, char* argv[])
{
pthread_t producer;
pthread_t consumer;
int result;
pthread_cond_init((pthread_cond_t * __restrict__)&products.notEmpty,NULL);
pthread_cond_init((pthread_cond_t * __restrict__)&products.notFull,NULL);
pthread_cond_init((pthread_cond_t * __restrict__)&products.locker,NULL);
pthread_create(&producer, NULL, &ProducerThread, NULL);
pthread_create(&consumer, NULL, &ConsumerThread, NULL);
pthread_join(producer, (void *)&result);
DB(printf("producer complete/n");)
pthread_join(consumer, (void *)&result);
DB(printf("consume complete/n");)

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: