【问题标题】:What to lock and what to not lock in a multithreaded environment (semaphores and shared memory)在多线程环境中锁定什么和不锁定什么(信号量和共享内存)
【发布时间】:2011-05-09 20:55:49
【问题描述】:

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

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

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

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

在这种情况下,我只是在内存中寻找一个字符。我想我不必担心为此设置信号量,不是吗?

如果我有类似的东西怎么办

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

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

谢谢!

【问题讨论】:

    标签: multithreading locking semaphore shared-memory


    【解决方案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)

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

    (在 .NET 和 JVM 等 IL 平台上,答案可能会略有不同,因为它们自己保证什么是原子的,什么不是)。

    【讨论】:

    • 所以,我不明白你的帖子的结论是什么?我应该锁定所有东西吗?
    • 被记录为原子的函数当然是原子的(假设它们不是错误的)。
    【解决方案2】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-01-13
      • 2012-08-03
      • 2013-11-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多