zoukankan      html  css  js  c++  java
  • 详解条件变量

    一年多过去啦,一段时间没有posix多线程的东西,又忘记的差不多略,我打记性咋这么差,丝毫记不起来怎么用啦,还是不如烂笔头啊。

    大家都知道条件变量需要配合mutex一起使用,往往是这样的:
    lock->signal->unlock,  而另一边呢是:

    lock->wait->unlock. 

    在调用pthread_cond_wait(cond,mutex)时的执行顺序是这样的:
    1. 首先获取外面的mutex, 然后当前wait push 到一个等待的queue里面,然后释放锁。但是你看wait的后面又是unlock释放mutex,这不重复啦吗?

        并不是这样,请继续往下看.

    2.  pthread_cond_signal 首先获取mutex, 然后通过条件变量发送消息,立刻释放mutex。

    3.  wait获取signal的消息,重新再获取mutex, 然后执行

    在研究pthread_cond_wait的时候总是会听到一局,wait结束后会重新获取锁,这句话很忽悠人,弄来好久才绕过来。

    pthread_cond_wait(cond, mutex), 可以展开来理解:

    pthread_mutex_unlock(mtx); 当然unlock之前把当前waitpush到queue里面
    pthread_cond_wait(cond);
    pthread_mutex_lock(mtx);

    从知乎上搜索也发现,有大神说:正是因为程序员发现unlock, wait, lock这三个操作始终得在一起,于是才提供略这个api来完成这三个动作。

    一个完整的顺序是这样的:

    A:
    pthread_mutex_lock(mtx);   -- a1 
    
    pthread_cond_wait(cond, mtx); 这一步需要展开:
    
    pthread_mutex_unlock(mtx);    -- a2
    
    pthread_cond_wait(cond);    -- a3
    
    pthread_mutex_lock(mtx); --a4

    pthread_mutex_unlock(mtx);    -- a5
    B:
    pthread_mutex_lock(mtx);   -- b1 
    
    pthread_cond_signal(cond);  -- b2
    
    pthread_mutex_unlock(mtx);    -- b3

    如果A先执行,顺序是:
    a1->a2->a3->b1->b2->a4->a5

    如果B先执行,顺序是:

    b1->b2-b3->a1->a2->a3, 不会进入a4,而是等待新的signal过来,之前一次的已经扔掉拉

    为什么需要加mutex???

    In Thread1:
    pthread_mutex_lock(&m_mutex);   
    pthread_cond_wait(&m_cond,&m_mutex);   
    pthread_mutex_unlock(&m_mutex);  
     
    In Thread2:
    pthread_mutex_lock(&m_mutex);   
    pthread_cond_signal(&m_cond);   
    pthread_mutex_unlock(&m_mutex);  

    假如1线程在调用cond_wait时,还没有进入wait_cond的状态, 然后线程2立马就调用啦cond_signal, 也就是signal比wait要快,这个时候cond_signal就丢失拉,使用啦mutex,则必须等到cond_wait的mutex释放后,然后线程2获取mutex, 然后才能调用cond_signal. 

    cond_signal为什么要放在mutex中间呢,放在unlock后面会怎么样呢?

    pthread_mutex_lock(&m_mutex);   
    
    xxxxxxx...
    pthread_mutex_unlock(&m_mutex); 
    pthread_cond_signal(&m_cond); 

    假如signal之前释放锁,这个时候有个低优先级的任务正在等待mutex, 而这个signal消息本是为啦去trigger一个更高优先级的线程的,这样就会出现低优先级抢占高优先级任务的现象,如果放在中间,则会先保证成功trigger本次需要trigger的任务后,然后释放锁,然后是其任务获取这个锁。

    放在中间有没有问题呢?其实也有:

    pthread_mutex_lock(&m_mutex);   
    pthread_cond_signal(&m_cond); 
    pthread_mutex_unlock(&m_mutex); 

    在某些线程的实现中,会造成等待线程从内核中唤醒(收到cond_signal)后又回到内核空间(出发cond_wait线程后然后又会获取mutex),会有性能问题。 

     
  • 相关阅读:
    119. Pascal's Triangle II
    118. Pascal's Triangle
    112. Path Sum
    111. Minimum Depth of Binary Tree
    110. Balanced Binary Tree
    108. Convert Sorted Array to Binary Search Tree
    88. Merge Sorted Array
    83. Remove Duplicates from Sorted List
    70. Climbing Stairs
    陌陌面试经历
  • 原文地址:https://www.cnblogs.com/biglucky/p/6309055.html
Copyright © 2011-2022 走看看