多线程编程的时候,一般需要在线程间交换数据。一般的做法是对公共变量加锁。锁一般是用互斥量,但是操作互斥量需要程序在用户态和核心态之间切换,有些性能损失。我一直在想有没有不用锁完成安全的进程间通信的办法?大部分情况是不可能,不过有一种情况,就是两个线程如果是以服务器-客户端模式工作,就有可能了,也许大家没注意到其实PostMessage这个API是线程安全的,但是我猜想它并没有用锁。这个API一般编程可以随便使用,但是你如果用MFC,微软会限制你跨线程投递窗口消息,就我的经验,其实跨线程投递窗口消息根本没问题,微软的限制是不是说明他没有用锁呢?
在什么情况下可以不用锁?准确的说,是一个线程向另一个线程的任务队列提交任务的时候,任务队列的实现必须是基于数组的固定长度队列,并且Pop和Push方法必须严格得分别限制在两个线程使用,如果一个线程能够插入数据,那它就不能提取数据,反过来也一样,这主要靠程序员自律,不过可以加入一些debug代码对这种错误报警。两个线程要交换数据就要用两个队列了。为什么是安全的呢,双线程操作队列有几种可能出现的错误,我推导一种:如果Pop端开始执行的时候,队列是空的,但是执行了一半,切换到Push端线程执行,push完成的时候,切换回Pop执行完成,这时如果Pop有空检查,那么返回结果是错误的,因为返回的时候,队列里有内容。但是这个错误对这个队列要实现的功能有没有影响?没有,任务提取系统都是循环运行的,下次循环到Pop的时候就会提出这次Push的数据处理了。还有其他几种情况,可以自己分析下看看。没错,所有的同步错误对功能的实现都没有任何影响。你可以用stl库的queue实验一下,不过这个类默认会自动增长的,注意我说的队列必须只能存在于固定的内存长度里。这里我解释一下,一般队列实现的时候都是申请比如int a[100]这样的空间,然后靠标记队列首尾来工作,自动增长不过是变成申请int *a=(int*)malloc(100*sizeof(int),增长的实现就是再申请一段更大的空间,然后把现在的数据拷贝过去。我说的是只能用第一种,因为自动增长会出问题,因为增长的时候一定要加锁同步。