您的位置:首页 > 运维架构 > Linux

LINUX 线程锁的设置不当案例(生产者消费者模型小BUG)

2016-11-03 17:36 471 查看
先上错误代码:
#include"../h.h"
#include<list>
#include<iostream>

typedef struct tasks
{
int a;
}tasks;
pthread_mutex_t mutex;
pthread_cond_t con;
std::list<tasks*> queue;
void * work_thread(void *p)
{
while(1)
{
pthread_mutex_lock(&mutex);
pthread_cond_wait(&con,&mutex);
printf("****\n");
pthread_mutex_unlock(&mutex);
while(1)
{
pthread_mutex_lock(&mutex);
if(queue.size()==0)
{
pthread_mutex_unlock(&mutex);
break;
}
std::list<tasks*>::iterator it = queue.begin();
tasks* task = *it;
printf("task is :%d\n",task->a);
delete task;
printf("*******delete*****\n");
queue.pop_front();
pthread_mutex_unlock(&mutex);
}
}
}
int main()
{
pthread_t work_t;
pthread_mutex_init(&mutex,NULL);
pthread_cond_init(&con,NULL);
pthread_create(&work_t,NULL,work_thread,NULL);
while(1)
{
pthread_mutex_lock(&mutex);
// printf("main lock\n");
int a;
std::cin >> a;

tasks* task = new tasks;
task->a= a;
queue.push_back(task);

pthread_mutex_unlock(&mutex);
pthread_cond_signal(&con);
printf("send signal OK\n");
}
return 0;
}

执行结果:

1                                 //输入数字

send signal OK

分析:主线程发信号之后子线程没有执行接收信号,一遍遍检查代码OK,扯掉一把头发之后,试着把加锁的位置换到了cin之后,OK了;

分析2:cin语句是阻塞的,而进程只有一把锁,主线程可以一直执行,子线程一直不能接收到信号,接收信号首先要得到锁,所以当加入cin之后必然是子线程可以得到锁,代码才可以继续执行;   

主函数获得锁之后打印  printf("main lock\n");可以看到,发送信号之后主线程马上又获得了锁,导致子线程一直不能执行;          

执行结果:

1

send signal OK

main lock

结论:

一般只在使用锁之前需要先安排好获得锁的顺序,且一般只在操作全局变量的时候加锁,可以提高效率;

主函数改为:

int main()
{
...
while(1)
{
int a;
std::cin >> a;

tasks* task = new tasks;
task->a= a;
pthread_mutex_lock(&mutex);
queue.push_back(task);

pthread_mutex_unlock(&mutex);
pthread_cond_signal(&con);
printf("send signal OK\n");
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  linux