使用信号量保护队列的问题 [英] Problem with using Semaphore to protect queue

查看:96
本文介绍了使用信号量保护队列的问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用以下代码来限制资源的使用.

I am using following code to limit use of resources.

一段时间(成功运行3-4天后),我得到队列为空的异常,或者发现返回的对象为空.

Once in a while(after 3-4 days of successful run) I get queue empty exception or the returned object is found to be null.

我想知道是否仅限制5个线程进入此Get方法,这是怎么发生的.

I am wondering if I am limiting only 5 threads to enter this Get method, how come this happens.

在Final块中肯定也调用了GetConnection的地方,即ReleaseConnection.

The places where GetConnection is called, ReleaseConnection is also definitely called within the Finally block.

每次通话,我都没有登录.队列中的资源数量.队列数量似乎从未超过5.

With each call, I am also logging no. of resources in the queue. The queue count never seems to be going more than 5.

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();
}

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

My question is, Do I need to synchronize the access to queue (resources instance), using lock/Monitor?

推荐答案

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

None of the standard .NET collections are thread-safe by default. They cannotbe accessed concurrently without some kind of memory barrier preventing concurrent access.

在您的情况下,信号量阻止五个以上的线程访问resources,但是没有任何措施阻止这五个并发线程中的任何一个同时进入Dequeue()Enqueue() .在这些线程之间极有可能发生罕见的竞争状况,这会导致队列损坏.您确实应该在resources队列本身周围加锁.

In your case, the semaphore prevents more than five threads from accessing resources but nothing prevents any of those five concurrent threads from entering Dequeue() or Enqueue() at the same time. It is entirely possible that a rare race condition occurs amongst those threads which results in the corruption of the queue. You should really put a lock around the resources queue itself.

在尝试调用Dequeue()之前,我还建议您在锁内进行测试 ,以确保队列中仍有要删除的项目.但是,由于我不知道您的代码如何工作的细节,因此请您自己决定是否相关.

I would also advise you perform a test inside the lock to make sure that the queue still has items to remove, before you attempt to call Dequeue(). However, since I don't know the specifics of how your code works, I leave it to you to decide if that's relevant.

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();
}

这篇关于使用信号量保护队列的问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆