2010-11-14 83 views
2

我正在实施一些简单的生产者/消费者程序,有一些信号量和共享内存。为了简单起见,我们假设我的程序中只有一块共享内存和一个信号量。什么来锁定和什么不锁定在多线程环境(信号量和共享内存)

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

现在,我有很多的代码看起来像这样:

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

在这种情况下,我只是希望在内存中的单个字符。我想我不必担心在这附近放置一个信号灯,对吧?

而且如果不是我有类似

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

从我的角度来看,我猜测,因为这是2点的操作,我不得不认为这是一个重要的部分,因此不必把一个什么信号周围。我对吗?

谢谢!

回答

1

从技术上讲,在多核或多处理器系统中,唯一的原子是汇编操作码,它们被明确记录为原子。即使读取单个字节也会给另一个处理器带来(非常小的)机会,并在读取它之前对其进行修改,除非在某些情况下处理CPU缓存和对齐的内存块(有趣的线程:http://software.intel.com/en-us/forums/showthread.php?t=76744,有趣的阅读:http://www.corensic.com/CorensicBlog/tabid/101/EntryId/8/Memory-Consistency-Models.aspx

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

(答案可能会略有上IL平台,如.NET和JVM上,因为他们对什么是原子,哪些不是自己的担保发生变化)。

+0

所以,我没有得到你的文章的结论是什么?我应该锁定一切吗? – 2010-11-14 16:51:22

+0

记录为原子的函数当然是原子的(假设它们不是越野车)。 – 2010-11-14 18:14:19

1

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