在多线程环境中锁定什么和不锁定什么(信号量和共享内存)
我正在实现一些简单的生产者/消费者程序,其中有一些信号量和共享内存。为了简单起见,我们假设我的程序中只有一块共享内存和一个信号量。
起初,我认为我只需要考虑尝试写入共享内存块的代码的关键部分。但是,由于共享内存块由 1024 字节组成,我无法同时读取所有数据(这不是原子操作),因此确实有可能在我从中读取数据时,生产者来并开始写入其中,因此读者将得到一半旧数据,一半新数据。由此,我只能认为我还必须将共享内存读取逻辑放入“信号量”块中。
现在,我有很多看起来像这样的代码:
if (sharedMemory[0] == '0') { ... }
在这种情况下,我只是在内存中寻找单个字符。我想我不必担心在这周围放置信号量,是吗?
如果我有类似的内容
if (sharedMemory[0] == '0' && sharedMemory[1] == '1') { ... }
,从我的角度来看,我想由于这是两个操作,我必须将其视为关键部分,因此必须在其周围放置一个信号量。我说得对吗?
谢谢!
I was implementing some simple Producer/Consumer program that had some semaphores and shared memory. To keep things simple, let's assume that there's just a block of shared memory and a semaphore in my program.
At first, I though that I only had to consider as critical section bits of code that'd try to write to the shared memory block. But as the shared memory block consists of, let's say, 1024bytes, I can't read all the data at the same time (it's not an atomic operation), so it is indeed possible that while I'm reading from it, the Producer comes and starts writing in it, so the reader will get half old data, half new data. From this, I can only think that I also have to put shared memory reading logic inside a "semaphore" block.
Now, I have lots of code that looks like this:
if (sharedMemory[0] == '0') { ... }
In this case, I am just looking for a single char in memory. I guess I don't have to worry about puting a semaphore around this, do I?
And what if instead I have something like
if (sharedMemory[0] == '0' && sharedMemory[1] == '1') { ... }
From my perspective, I guess that as this are 2 operations, I'd have to consider this as a critical section, thus having to put a semaphore around it. Am I right?
Thanks!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
从技术上讲,在多核或多处理器系统上,唯一原子的是汇编操作码,它们被专门记录为原子。即使读取单个字节也有(非常小的)机会,另一个处理器会在您读取它之前出现并对其进行修改,除非在某些情况下处理 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 平台上,答案可能会略有不同,因为它们对什么是原子的、什么不是原子做出自己的保证)。
Technically, on a multicore or multiprocessor system the only thing that's atomic are assembly opcodes which are specifically documented as being atomic. Even reading a single byte presents a (quite small) chance the another processor will come along and modify it before you're doing reading it, except in some cases that deals with CPU cache and aligned chunks of memory (Fun thread: http://software.intel.com/en-us/forums/showthread.php?t=76744, Interesting read: http://www.corensic.com/CorensicBlog/tabid/101/EntryId/8/Memory-Consistency-Models.aspx)
You must either use types which internally guarantee atomicity or specifically protect accesses on multithreaded multicore systems.
(The answer may change slightly on IL platforms like .NET and JVMs since they make their own guarantees about what's atomic and what isn't).
绝对锁定非原子操作,并且检查两个不同的值被视为非原子操作,尽管您可以使用一些技巧来检查最多四个字节或更多字节,前提是您的处理器不缓存结果。您必须考虑如何使用您的数据。但基本上,对共享内存的任何访问都应该有一个信号量。
Definitely lock around non-atomic operations, and checking two different values counts as as a non-atomic operation, although there are tricks you can use to check up to four bytes or more, provided your processor doesn't cache the results. You have to consider how your data is used. But basically, any access to shared memory should have have a semaphore around it.