前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >线程同步(二)—— 条件变量

线程同步(二)—— 条件变量

作者头像
Aichen
发布2018-05-18 11:47:11
9560
发布2018-05-18 11:47:11
举报
文章被收录于专栏:白驹过隙白驹过隙

上篇提到线程针对临界值操作时需要加锁,但是线程访问临界资源只通过锁来控制是不够的。 比如对一个数据进行操作,A线程需要读,B线程进行写。 A线程先访问临界资源,发现没有数据可以读,只能等待B线程先写,此时又占用了互斥锁,导致B线程无法得到锁,进行写操作。 此时就需要用到条件变量了,条件变量的目的就是控制线程的先后执行,保证临界资源的有效性。

下面依然是售票的一个场景,此时一个线程售票,一个线程退票。

代码语言:javascript
复制
#include <pthread.h>  
#include <unistd.h>  
#include <iostream>

using namespace std;

class ThreadInterface
{
public:
    void CreateThread(void* (*func)(void *));
    void WaitThread();
private:
    pthread_t m_pTread;   
};

void ThreadInterface::CreateThread(void* (*func)(void *))
{
    pthread_create(&m_pTread, NULL, func, NULL); 
}

void ThreadInterface::WaitThread()
{
    pthread_join(m_pTread, NULL); 
}

class MutexLockInterface
{
public:
    void CreateMutexLock();
    void GetMutexLock();
    void ReleaseMutexLock();
    void DestroyMutexLock();  
    pthread_mutex_t m_MutexLock;  
};

void MutexLockInterface::CreateMutexLock()
{
    int ret = pthread_mutex_init(&m_MutexLock, NULL);
    if (0 != ret)
        cout<<"init mutex error!";
}

void MutexLockInterface::GetMutexLock()
{
    pthread_mutex_lock(&m_MutexLock);
}

void MutexLockInterface::ReleaseMutexLock()
{
    pthread_mutex_unlock(&m_MutexLock);
}

void MutexLockInterface::DestroyMutexLock()
{
    pthread_mutex_destroy(&m_MutexLock);
}

class CondInterface
{
public:
    void CreateCond();
    void WaitCond(pthread_mutex_t *mutex);
    void WakeupCond();
    void DestroyCond();
private:
    pthread_cond_t m_Cond;
};

void CondInterface::CreateCond()
{
    int ret = pthread_cond_init(&m_Cond, NULL);
    if (0 != ret)
        cout<<"init mutex error!";
}
void CondInterface::WaitCond(pthread_mutex_t *mutex)
{
    pthread_cond_wait(&m_Cond, mutex);
}
void CondInterface::WakeupCond()
{
    pthread_cond_broadcast(&m_Cond);
}
void CondInterface::DestroyCond()
{
    pthread_cond_destroy(&m_Cond);
}

class Service
{
public:
    static void* run(void *)
    {
        m_MutexLock.GetMutexLock();
        cout<<"we have "<<m_Tickets<<"Tickets"<<endl;
        sleep(1);
        m_Tickets++;
        //Cond.WakeupCond();
        m_MutexLock.ReleaseMutexLock();
    }
    int SetData(int data){m_Tickets = data;};
    int GetData(){return m_Tickets;};
    static int m_Tickets;
    static MutexLockInterface m_MutexLock;
    static CondInterface Cond;
};
int Service::m_Tickets = 0;
MutexLockInterface Service::m_MutexLock;
CondInterface Service::Cond;

int main()
{
    Service Srv;
    ThreadInterface Thread;
    Srv.m_MutexLock.CreateMutexLock();
    Srv.Cond.CreateCond();
    Thread.CreateThread(&Srv.run);

    Srv.m_MutexLock.GetMutexLock();
    if (0 == Srv.GetData())
    {
        //Srv.Cond.WaitCond(&Srv.m_MutexLock.m_MutexLock);
        cout<<"wait!"<<endl;
    }
    
    cout<<"window1:we have "<<Srv.GetData()<<"Tickets"<<endl;
    sleep(1);
    Srv.SetData(Srv.GetData() - 1);
        
    Srv.m_MutexLock.ReleaseMutexLock();
    Thread.WaitThread();
    cout<<Srv.GetData()<<endl;
    return 0;
}

不使用条件变量执行结果如下:

线程1先执行,此时并没有票。此时应该先放弃锁,让线程2先执行,取消注释执行结果如下:

由此可以看出,条件变量让线程1暂时先放弃锁进入阻塞,等线程2执行完毕后,唤醒线程1。再进行正确操作。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2016-05-02 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档