C++ 并发问题

41 篇文章 0 订阅
15 篇文章 0 订阅

 

1.pthread_cond_wait的 虚假唤醒

什么是虚假唤醒?简单说就是wait这个函数返回了,但是它等的那个条件并不满足。

为什么会这样? 有两种原因

  1. 这个条件从来就没有满足过,wiat函数的返回不是因为别的线程调用signal或者broadcast把你唤醒,而是因为wait函数被信号中断。(虚假唤醒的一个可能性是条件变量的等待被信号中断。)

    pthread 的条件变量等待 pthread_cond_wait 是使用阻塞的系统调用实现的(比如 Linux 上的 futex),这些阻塞的系统调用在进程被信号中断后,通常会中止阻塞、直接返回 EINTR 错误。

    同样是阻塞系统调用,你从 read 拿到 EINTR 错误后可以直接决定重试,因为这通常不影响它本身的语义。而条件变量等待则不能,因为本线程拿到 EINTR 错误和重新调用 futex 等待之间,可能别的线程已经通过 pthread_cond_signal 或者 pthread_cond_broadcast发过通知了。(也就是说你准备重新等待的时候,你女神发短信说答应跟你在一起了,但是你这时候把手机给扔了,继续等待,直接gg)。

    所以对条件的判断要放在while里面。

    信号:内核给一个进程发送软中断信号的方法,是在进程所在的进程表项的信号域设置对应于该信号的位。这里要补充的是,如果信号发送给一个正在睡眠的进程,那么要看 该进程进入睡眠的优先级,如果进程睡眠在可被中断的优先级上,则唤醒进程;否则仅设置进程表中信号域相应的位,而不唤醒进程。这一点比较重要,因为进程检 查是否收到信号的时机是:一个进程在即将从内核态返回到用户态时;或者,在一个进程要进入或离开一个适当的低调度优先级睡眠状态时。 

    转自: https://www.cnblogs.com/sure/p/3782773.html

    第二个要 引起注意的是,如果要捕捉的信号发生于进程正在一个系统调用中时,并且该进程睡眠在可中断的优先级上,这时该信号引起进程作一次longjmp,跳出睡眠 状态,返回用户态并执行信号处理例程。当从信号处理例程返回时,进程就象从系统调用返回一样,但返回了一个错误代码,指出该次系统调用曾经被中断。这要注 意的是,BSD系统中内核可以自动地重新开始系统调用。 

    第三个要注意的地方:若进程睡眠在可中断的优先级上,则当它收到一个要忽略的信号时,该进程被唤醒,但不做longjmp,一般是继续睡眠。但用户感觉不到进程曾经被唤醒,而是象没有发生过该信号一样。 

    2、 这个条件曾经满足过,但是被人截胡了。由于线程调度的原因,被条件变量唤醒的线程A在本线程内真正执行「加锁并返回」前,另一个线程B也被唤醒了,并且比你更快,直接已经完整地进行了一套「拿锁、改条件、还锁」的操作。那这时候等到你拿锁的时候,条件变量实际上已经不满足了。(不管broadcast还是signal,实际都会不止唤醒一个线程,signal是为了性能的考虑,unp有关于这一点的说明)

怎么办?

其实就是把对条件的判断放在while循环里,而不能用if语句。

条件变量:https://www.ibm.com/developerworks/cn/linux/thread/posix_thread3/index.html

虚假唤醒:https://www.zhihu.com/question/271521213

 

条件变量使用方法:

pthread_mutex_lock(&m_mutex);
while(Work !=4){
    pthread_cond_wait(&m_cond,&m_mutex);
}

//对work do something

pthread_unlock(&m_mutex);

 

2. 并发模型

2. reactor和proactor

其实我也不是很理解,只理解了一个区别是reactor 是同步I/O操作,Proactor是异步I/O操作

https://www.zhihu.com/question/26943938

  1.  



  2.  

     

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值