信号量竞争条件?
我创建了一个“Manager”类,其中包含一组有限的资源。资源作为队列存储在“管理器”中。我将队列和信号量初始化为相同的大小,如果没有可用资源,则使用信号量来阻塞线程。我有多个线程调用此类来请求资源。这是伪代码:
public IResource RequestResource()
{
IResource resource = null;
_semaphore.WaitOne();
lock (_syncLock)
{
resource = _resources.Dequeue();
}
return resource;
}
public void ReleaseResource(IResource resource)
{
lock (_syncLock)
{
_resources.Enqueue(resource);
}
_semaphore.Release();
}
运行此应用程序时,它似乎运行良好一段时间。然后,我的队列似乎发出了相同的对象。这看起来可能吗?我正在这里拉我的头发,任何帮助将不胜感激。如果您需要更多信息,请随时询问。谢谢!
I have created a "Manager" class that contains a limited set of resources. The resources are stored in the "Manager" as a Queue. I initialize the Queue and a Semaphore to the same size, using the semaphore to block a thread if there are no resources available. I have multiple threads calling into this class to request a resource. Here is the psuedo code:
public IResource RequestResource()
{
IResource resource = null;
_semaphore.WaitOne();
lock (_syncLock)
{
resource = _resources.Dequeue();
}
return resource;
}
public void ReleaseResource(IResource resource)
{
lock (_syncLock)
{
_resources.Enqueue(resource);
}
_semaphore.Release();
}
While running this application, it seems to run fine for a while. Then, it seems like my Queue is giving out the same object. Does this seem like its possible? I'm pulling my hair out over here, and any help would be greatly appreciated. Feel free to ask for more information if you need it. Thanks!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
信号量在这里确实是偶然的;这只是限制了可以同时获取资源的消费者数量。同步实际上来自
lock
语句(临界区)。据我所知,该代码是线程安全的。当你说它“给出相同的对象”时 - 也许我误解了这个问题,但它应该给出相同的对象,因为当调用者调用
Release
时方法时,它们会放回最初获得的相同资源,因此在执行过程中,同一个对象将在多个时刻出现在队列中。如果您的意思是
RequestResource
方法返回已获取但未释放的资源,我能想到的只有三个可能的原因:队列包含来自begin;
消费者调用了
Release
方法两次。在您的Release
方法中,您实际上并不检查资源是否已经回到队列中;而是检查资源是否已返回队列。您可能需要更改此代码来检查这一点并引发异常,这将帮助您捕获Release
调用被重复的位置(如果事实确实如此)。其他一些代码在没有
锁
的情况下访问_resources
队列。如果这确实是你所说的重复的意思,我的怀疑是#2。
The semaphore is really incidental here; that just limits the number of consumers that can acquire resources at the same time. The synchronization is actually coming from the
lock
statement (critical section).As far as I can tell, that code is thread-safe. When you say it's "giving out the same object" - maybe I'm misunderstanding the question, but it should be giving out the same object, because when callers invoke the
Release
method, they put back the same resource they got originally, so the same object will be in the queue at several points during execution.If what you mean is that the
RequestResource
method is returning resources that have already been acquired but not released, there are only three possible reasons that I can think of:The queue contained duplicate resources from the beginning;
A consumer called the
Release
method twice. In yourRelease
method, you don't actually check to see whether or not the resource is already back in the queue; you might want to alter this code to check for this and throw an exception, which would help you catch whereRelease
calls are being duplicated (if this is in fact the case).Some other code is accessing the
_resources
queue without alock
.My suspicion would be #2, if this is indeed what you mean by duplicates.
除了 Aaronaught 的回答之外:
两个线程获取信号量,然后一个线程进入 RequestResource() 中的关键部分,另一个线程块,然后第一个线程完成,这看起来也是完全可能的在第二个线程醒来并有机会出队之前,使用
ReleaseResource()
将对象返回到队列。这会给人一种两个线程获取同一个对象的印象。In addition to Aaronaught's answer:
It also looks entirely possible for two threads to acquire the semaphore, then one to enter the critical section in
RequestResource()
, and the the other block, followed by the first thread completing all its work and returning the object to the queue withReleaseResource()
before the second thread waking up and having a chance to dequeue. That would give an impression of two threads obtaining the same object.