首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用信号量保护队列的问题

使用信号量保护队列的问题
EN

Stack Overflow用户
提问于 2010-02-17 08:53:55
回答 2查看 3.6K关注 0票数 1

我使用下面的代码来限制资源的使用。

偶尔(在成功运行3-4天后)我会得到队列空异常,或者返回的对象被发现为空。

我想知道如果我只限制了5个线程进入这个Get方法,为什么会发生这种情况。

在调用GetConnection的地方,ReleaseConnection也肯定是在Finally块中调用的。

对于每个调用,我也记录了no。队列中的资源。队列计数似乎永远不会超过5。

代码语言:javascript
复制
Semaphore smphSync = new Semaphore(0, 5);

Queue<IResource> resources;

private IResource GetResource()

{

    smphSync.WaitOne();

    IResource res = resources.Dequeue();

    return res;
}

private ReleaseResource(IResource res)

{

    resources.Enqueue(res);

    smphSync.Release();
}

我的问题是,我是否需要使用锁/监视器来同步对队列(资源实例)的访问?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2010-02-17 09:03:06

默认情况下,所有标准的.NET集合都不是线程安全的。它们是_cannot_be并发访问的,没有某种内存屏障来阻止并发访问。

在您的例子中,信号量阻止五个以上的线程访问Dequeue(),但不会阻止这五个并发线程中的任何一个同时进入 resources 。完全有可能在这些线程之间发生罕见的竞争条件,从而导致队列损坏。您真的应该在resources队列本身周围设置一个锁。

我还建议您在尝试调用Dequeue()之前,在锁内执行一个测试,以确保队列中仍有要删除的项。但是,由于我不知道您的代码是如何工作的,所以我让您来决定这是否相关。

代码语言:javascript
复制
Semaphore smphSync = new Semaphore(0, 5);
Queue<IResource> resources;
private _lockObj = new object();

private IResource GetResource()
{
    smphSync.WaitOne();
    lock( _lockObj ) 
    {
        IResource res = resources.Dequeue();
        return res;
    }
}

private ReleaseResource(IResource res)
{
    lock( _lockObj )
    {
        resources.Enqueue(res);
    }
    smphSync.Release();
}
票数 3
EN

Stack Overflow用户

发布于 2010-02-17 08:58:46

我在我的锁类周围添加了ThreadSafeQueue (),最近还添加了一个TryDequeue()方法。更多详细信息,请访问this post。绝对改进了我以前经常看到的多线程冲突(最明显的是,当队列中不存在空值时,返回一个空对象)。

编辑:签入了TryDequeue()方法,并更新了指向正确变更集的链接。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/2277603

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档