Linux环境下线程消息同步的陷阱

来源:互联网 发布:mdf和ldf恢复数据库 编辑:程序博客网 时间:2024/06/17 02:25

我们程序中常常会使用到线程间的消息同步处理,比如以下一段伪码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
var message = ""
void func() 
{
  1. 启动线程Thread(该线程中填充message的内容);
 
  2. 阻塞,直到等待到完成message填充的事件;
 
  3. 处理message;
 
  ....
}
void Thread() 
{
  1. 通过某种处理填充message;
 
  2. 触发func中的阻塞事件;
}


我们通常会使用条件变量来完成类似情况的线程同步处理

  • 比如windows平台下CreateEvent,WaitForSingleObject,SetEvent...;

  • Linux平台下的pthread_cond_init,pthread_cond_wait,pthread_cond_signal...。


      看上去很完美的模型。但是在Linux平台下使用条件变量来完成这种需求是有风险的,要知道操作系统对线程的调度是我们不可控的。设想这样一种情况:func中步骤1的线程有可能已经触发了阻塞事件,但是func步骤2还未执行。这时这个事件如果在Linux平台下使用条件变量就会丢失通知。这样对于步骤2就面临着永远阻塞或者超时这些我们不期望的逻辑。(这种情况在我写的客户端网络SDK的linux版本下遇过的,我发出去一条带有标识的消息,然后利用条件变量阻塞10秒等待这个标识消息,但是时常会遇见等待超时的情况,按说是不可能超时的,最后经过详细调查才发现是由于pthread库的条件变量触发机制导致的。)但是在windows下使用Event却不会出现这种情况。

举个简单的例子:

  • linux下pthread库的条件变量触发机制好比:你和女神妹子约好在某个地方见面,理应你先到的,结果因为你堵车妹子先到了,一看你没来,生气走了。约会泡汤,哭去吧你。

  • windows下的事件的触发机制好比:你和屌丝妹子约好在某个地方见面,理应你先到,但你故意晚来想气走妹子,结果妹子先到却一直等你。约会进行中,哭去吧你。

那么我们有没有办法在linux平台下实现一种更可靠的消息同步机制,屌丝福音:使用posix信号量sem_init,sem_t imedwait,sem_post...。另外使用select和epoll的水平触发也可以变向实现这种情况下的消息同步(监控管道一端的读,一端写来触发消息)。

推荐阅读:《Linux 的多线程编程的高效开发经验》

0 0
原创粉丝点击