生产者-消费者模型 - 二进制信号量还是互斥体?
这主要是概念的理解,让我很困惑。
互斥是指一个线程控制共享资源的访问,执行操作并解锁它,然后只有其他线程才能获得锁的访问权,
而二进制信号量就像一个线程可以访问共享资源,但可以访问锁,而另一个线程可以解锁它
在我看到的最后一个问题 这里,提到“信号量更适合一些同步问题,例如生产者-消费者”。
我的问题例如,如果生产者线程获得了锁并用数据填充了某个队列,而消费者同时解锁了它,那么是否存在并发问题?
This is mainly about the understanding of the concept, which confuses me.
Mutex means that one thread takes the control of the access of shared resource, performs operations and unlocks it, then only other thread can gain access to lock
while binary semaphore is like a thread can gain access to the shared resource but gaining access to the lock, while another thread can unlock it
In the last question that I saw over here, it was mentioned that "semaphores are more suitable for some synchronization problems like producer-consumer".
My question is, for example, if producer thread has gained lock and filling up some queue with data, and consumer at the same time unlocks it, isn't there any concurrency issue??
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我会尽力解决这个困惑。我将按照传统定义的方式解释这些概念。问题是人们开始混淆其中许多概念的含义,从而产生了很多混乱。
每当我们有一段代码修改在不同进程或线程之间共享的一点内存(例如变量)时,我们就有一个临界区。如果我们不注意正确同步这段代码,那么我们就会遇到错误。临界区的一个例子是生产者将一个元素添加到某种共享容器中。
同步关键部分的一种方法是强制互斥。互斥意味着一次只有一个进程或线程可以执行临界区并访问共享内存。请注意,互斥本身并不是一种机制,而是我们可以通过不同方式强制执行的原则。有些人将锁和二进制信号量视为互斥体,但这以一种会导致混乱的方式混合了这些概念。
二进制信号量是一种强制互斥的方法。每当进程想要访问互斥体时,它就可以获取信号量。如果此时有另一个进程持有该信号量,则该操作将被阻塞。因此我们之间存在着相互排斥。一旦进程使用互斥体完成,我们就释放信号量,让其他进程进入互斥体。这样我们就可以用二值信号量来实现互斥,但这绝不是二值信号量唯一可能的应用。
信号量对于生产者-消费者问题非常有用,因为它们可以采用任意自然数,而不仅仅是二进制信号量中的 0 和 1。这在同步生产者-消费者问题时非常有用,因为您可以让信号量的值包含可用元素的数量。如果元素数量减至零,则信号量操作将自动阻塞。
我意识到对生产者-消费者问题的解释有点简短,我鼓励您查看使用信号量的解决方案,并将这些解决方案与使用其他同步结构(例如监视器或消息传递)的其他解决方案进行比较。我发现它非常有启发性。
I'll try to sort out the confusion the best I can. I will explain the concepts the way they are traditionally defined. The problem is that people start to mix the meaning of many of these concepts and a lot of confusion arise from that.
Whenever we have a piece of code that modifies a bit of memory (say a variable) that is shared between different processes or threads we have a critical section. If we don't take care to synchronize this bit of code properly then we will get bugs. One example of a critical section is a producer adding an element to a shared container of some sort.
One way to synchronize critical sections is to enforce mutual exclusion. Mutual exclusion means that only one process or thread at a time can execute the critical section and gain access to the shared piece of memory. Note that mutual exclusion is not a mechanism in it self, it is a principle that we can enforce by different means. Some people talk about locks and binary semaphores as mutexes but that mixes the concepts in a way that will lead to confusion.
A binary semaphore is a way to enforce mutual exclusion. Whenever a process wants to get access to the mutex it can aquire the semaphore. This operation will block if there is another process holding the semaphore at that moment. Hence we have mutual exclusion. Once a process is done with the mutex then we releases the semaphore letting other processes into the mutex. In this way we can achieve mutual exclusion with a binary semaphore, but it is by no means the only possible application of a binary semaphore.
Semaphores are nice for producer-consumer problems because they can take on an arbitrary natural number, not just 0 and 1 in the case of binary semaphores. This is very useful when synchronizing producer-consumer problems because you can let the value of a semaphore contain the number of available elements. If the number of elements go down to zero then the semaphore operations will automatically block.
I realize the explanation of the producer-consumer problem is a bit brief and I encourage you to look at solutions which uses semaphores and also compare these solutions to other solutions which uses other synchronization constructs such as monitors or message passing. I've found it to be very illuminating.