在多线程环境中锁定什么以及不锁定什么(信号量和共享内存)

时间:2010-11-14 16:37:26

标签: multithreading locking semaphore shared-memory

我正在实现一些简单的Producer / Consumer程序,它有一些信号量和共享内存。为了简单起见,我们假设程序中只有一块共享内存和一个信号量。

首先,我只是考虑作为试图写入共享内存块的代码的关键部分。但是由于共享内存块由1024字节组成,我无法同时读取所有数据(它不是原子操作),所以当我从它读取时,确实可能是生产者来了,开始写它,所以读者将获得一半的旧数据,一半的新数据。由此,我只能认为我还必须将共享内存读取逻辑放在“信号量”块中。

现在,我有很多代码如下:

if (sharedMemory[0] == '0') { ... }

在这种情况下,我只是在内存中寻找一个char。我想我不必担心在这周围放一个信号量,对吗?

如果相反我会有类似

的内容
if (sharedMemory[0] == '0' && sharedMemory[1] == '1') { ... }

从我的角度来看,我认为由于这是两个操作,我不得不将其视为一个关键部分,因此必须在它周围放置一个信号量。我是对的吗?

谢谢!

2 个答案:

答案 0 :(得分:1)

绝对锁定非原子操作,并检查两个不同的值计为非原子操作,尽管有一些技巧可用于检查最多四个字节或更多,前提是您的处理器不会缓存结果。您必须考虑如何使用您的数据。但基本上,对共享内存的任何访问都应该有一个信号量。

答案 1 :(得分:1)

从技术上讲,在多核或多处理器系统上,唯一的原子是装配操作码,具体记录为原子。即使读取单个字节也会有一个(相当小的)机会,另一个处理器会在你读它之前出现并修改它,除非在某些情况下处理CPU缓存和对齐的内存块(Fun thread:{{3有趣的阅​​读:http://software.intel.com/en-us/forums/showthread.php?t=76744

您必须使用内部保证原子性的类型或专门保护多线程多核系统上的访问。

(对于像.NET和JVM这样的IL平台,答案可能略有改变,因为它们对原子和非原子的内容做出了自己的保证。)