• 详解条件变量


    一年多过去啦,一段时间没有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),会有性能问题。 

     
  • 相关阅读:
    XML与JSON的对比
    WPF dataGrid下的ComboBox的绑定
    WPF 导出Excel(合并单元格)
    WPF x:key和x:name用法
    WPF Canvas
    WPF Visibility属性用法
    AxInterop.ShockwaveFlashObjects.dll 问题
    BadImageFormatException,未能加载正确的程序集XXX的解决办法
    inner join ,left join ,right join区别
    Mac系统下php.ini的位置
  • 原文地址:https://www.cnblogs.com/biglucky/p/6309055.html
Copyright © 2020-2023  润新知