试想一个场景,对一个链表取数据和存入数据,线程安全,可以做到一对一,一对多或者多对多,,先不考虑无锁实现,
对于互斥锁,只需在读和写的时候加锁,就可以做到线程安全,但是有一个问题,假如链表数据为空的时候,常规的做法是循环睡眠检测是否有数据,这样就浪费了cpu时间片,改进措施就是用条件变量
条件变量:条件变量不同于信号量,没有计数概念,就是说如果产生的信号没有条件变量等待,那么该信号就是丢失,不会有累计的概念,条件变量等待信号也没有消耗的说法。同时也解释下pthread_cond_wait原理,和一个锁搭配使用,在使用之前上锁,然后pthread_cond_wait内部里面会解锁,等待一个条件变量信号的发生,当条件变量等待到信号返回时又上锁(这个过程是pthread_cond_wait内部),外面又解锁,这两种行为是一个互斥,一个等待,为了解决一些特殊场景!
前面场景的改进就是如果没有数据,那么就等待有数据,减少cpu的无效占用,,看我代码吧,条件变量不好就在于等待和上锁时要分开,不能写死在一个函数内,看我下面消费和产生数据的线程
class Mycondition_mutex{
public:
Mycondition_mutex(){
pthread_cond_init(&m_cond,NULL);
pthread_mutex_init(&m_mutex,NULL);
}
~Mycondition_mutex()
{
pthread_cond_destroy(&m_cond);
pthread_mutex_destroy(&m_mutex);
}
void lock()
{
pthread_mutex_lock(&m_mutex);
}
void unlock()
{
pthread_mutex_unlock(&m_mutex);
}
void wait()
{
//pthread_mutex_lock(&m_mutex);
pthread_cond_wait(&m_cond,&m_mutex);
//pthread_mutex_unlock(&m_mutex);
}
void signal()
{
// pthread_mutex_lock(&m_mutex);
//pthread_cond_signal(&m_cond);
pthread_cond_broadcast(&m_cond);
//pthread_mutex_unlock(&m_mutex);
}
private:
pthread_cond_t m_cond;
pthread_mutex_t m_mutex;
};
void* produce(void *p)
{
list<int>* ilist= (list<int>*)p;
while(1)
{
g_cond.lock();
if(data==1E+8)
{
flag=1;
cout << "produce" << data << endl;
g_cond.unlock();
break;
}
ilist->push_back(data);
//cout<<"produce data:"<<data<<endl;
data++;
if(wait_flag==1)
{
//cout << "sigmal one" << endl;
g_cond.signal();
wait_flag=0;
}
g_cond.unlock();
}
return (void*)1;
}
void* consume(void *p)
{
list<int>* ilist= (list<int>*)p;
while(1)
{
g_cond.lock();
if(ilist->empty())
{
if(flag==1)
{
g_cond.unlock();
break;
}
else
{
//g_lock.unlock();
wait_flag=1;
g_cond.wait();
g_cond.unlock();
continue;
}
}
int len=ilist->size();
int data=ilist->front();
ilist->pop_front();
//if(data==1999999)
//cout<<"consume data:"<<data<<endl;
g_cond.unlock();
}
return (void*)1;
}
这个列子是我为了测试多线程下存取数据的效率,还没过渡到无锁实现,如果存数据之前、取数据之后有一系列的操作,多线程才能发挥效率,在我这个场景里面看到的是某一时刻只有一个线程在存取操作。
Mycondition_mutex g_cond;
int flag=0;
int data=0;
int wait_flag=0;
int main()
{
list<int> ilist;
pthread_t pro[5],con[5];
for (int i = 0; i <5; i++)
pthread_create(&con[i], NULL, consume, (void*)&ilist);
for (int i = 0; i <5; i++)
pthread_create(&pro[i],NULL,produce,(void*)&ilist);
pthread_join(pro[0],0);
pthread_join(pro[1],0);
pthread_join(pro[2], 0);
pthread_join(pro[3], 0);
pthread_join(pro[4], 0);
pthread_join(con[0],0);
pthread_join(con[1],0);
pthread_join(con[2], 0);
pthread_join(con[3], 0);
pthread_join(con[4], 0);
return 0;
};
下一步进军无锁队列的实现!