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


    上篇提到线程针对临界值操作时需要加锁,但是线程访问临界资源只通过锁来控制是不够的。

    比如对一个数据进行操作,A线程需要读,B线程进行写。

    A线程先访问临界资源,发现没有数据可以读,只能等待B线程先写,此时又占用了互斥锁,导致B线程无法得到锁,进行写操作。

    此时就需要用到条件变量了,条件变量的目的就是控制线程的先后执行,保证临界资源的有效性。

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

      1 #include <pthread.h>  
      2 #include <unistd.h>  
      3 #include <iostream>
      4 
      5 using namespace std;
      6 
      7 class ThreadInterface
      8 {
      9 public:
     10     void CreateThread(void* (*func)(void *));
     11     void WaitThread();
     12 private:
     13     pthread_t m_pTread;   
     14 };
     15 
     16 void ThreadInterface::CreateThread(void* (*func)(void *))
     17 {
     18     pthread_create(&m_pTread, NULL, func, NULL); 
     19 }
     20 
     21 void ThreadInterface::WaitThread()
     22 {
     23     pthread_join(m_pTread, NULL); 
     24 }
     25 
     26 class MutexLockInterface
     27 {
     28 public:
     29     void CreateMutexLock();
     30     void GetMutexLock();
     31     void ReleaseMutexLock();
     32     void DestroyMutexLock();  
     33     pthread_mutex_t m_MutexLock;  
     34 };
     35 
     36 void MutexLockInterface::CreateMutexLock()
     37 {
     38     int ret = pthread_mutex_init(&m_MutexLock, NULL);
     39     if (0 != ret)
     40         cout<<"init mutex error!";
     41 }
     42 
     43 void MutexLockInterface::GetMutexLock()
     44 {
     45     pthread_mutex_lock(&m_MutexLock);
     46 }
     47 
     48 void MutexLockInterface::ReleaseMutexLock()
     49 {
     50     pthread_mutex_unlock(&m_MutexLock);
     51 }
     52 
     53 void MutexLockInterface::DestroyMutexLock()
     54 {
     55     pthread_mutex_destroy(&m_MutexLock);
     56 }
     57 
     58 class CondInterface
     59 {
     60 public:
     61     void CreateCond();
     62     void WaitCond(pthread_mutex_t *mutex);
     63     void WakeupCond();
     64     void DestroyCond();
     65 private:
     66     pthread_cond_t m_Cond;
     67 };
     68 
     69 void CondInterface::CreateCond()
     70 {
     71     int ret = pthread_cond_init(&m_Cond, NULL);
     72     if (0 != ret)
     73         cout<<"init mutex error!";
     74 }
     75 void CondInterface::WaitCond(pthread_mutex_t *mutex)
     76 {
     77     pthread_cond_wait(&m_Cond, mutex);
     78 }
     79 void CondInterface::WakeupCond()
     80 {
     81     pthread_cond_broadcast(&m_Cond);
     82 }
     83 void CondInterface::DestroyCond()
     84 {
     85     pthread_cond_destroy(&m_Cond);
     86 }
     87 
     88 class Service
     89 {
     90 public:
     91     static void* run(void *)
     92     {
     93         m_MutexLock.GetMutexLock();
     94         cout<<"we have "<<m_Tickets<<"Tickets"<<endl;
     95         sleep(1);
     96         m_Tickets++;
     97         //Cond.WakeupCond();
     98         m_MutexLock.ReleaseMutexLock();
     99     }
    100     int SetData(int data){m_Tickets = data;};
    101     int GetData(){return m_Tickets;};
    102     static int m_Tickets;
    103     static MutexLockInterface m_MutexLock;
    104     static CondInterface Cond;
    105 };
    106 int Service::m_Tickets = 0;
    107 MutexLockInterface Service::m_MutexLock;
    108 CondInterface Service::Cond;
    109 
    110 int main()
    111 {
    112     Service Srv;
    113     ThreadInterface Thread;
    114     Srv.m_MutexLock.CreateMutexLock();
    115     Srv.Cond.CreateCond();
    116     Thread.CreateThread(&Srv.run);
    117 
    118     Srv.m_MutexLock.GetMutexLock();
    119     if (0 == Srv.GetData())
    120     {
    121         //Srv.Cond.WaitCond(&Srv.m_MutexLock.m_MutexLock);
    122         cout<<"wait!"<<endl;
    123     }
    124     
    125     cout<<"window1:we have "<<Srv.GetData()<<"Tickets"<<endl;
    126     sleep(1);
    127     Srv.SetData(Srv.GetData() - 1);
    128         
    129     Srv.m_MutexLock.ReleaseMutexLock();
    130     Thread.WaitThread();
    131     cout<<Srv.GetData()<<endl;
    132     return 0;
    133 }

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

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

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

  • 相关阅读:
    [Django]Windows下Django配置Apache示范设置
    《职场》笔记20061119
    Python Django还是RoR,这是一个问题
    收集证据:fsjoy.com的流氓推广和幕后流氓主子[updated]
    爱尔兰网友邀请我对Dublin交通监视器进行手机端开发
    {基于Applet的J2ME模拟器}和{microemulator}[J2ME推荐]
    中国移动IM飞信0802上线新版本 试用手记
    [AsyncHandle]什么引发了ObjectDisposedException?
    百度的“搜索背后的人”的战略
    [Python]检查你的站点的人气
  • 原文地址:https://www.cnblogs.com/binchen-china/p/5453216.html
Copyright © 2020-2023  润新知