信号量由于停止在自己的线程上运行的代码而陷入僵局

信号量由于停止在自己的线程上运行的代码而陷入僵局

本文介绍了信号量由于停止在自己的线程上运行的代码而陷入僵局的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

为了能够运行在多线程环境中无法很好扩展的库,我创建了一个对象池来自动创建有限数量的实例,以增加总吞吐量.我正在使用 SemaphoreSlim 锁定/解锁对基础实例的访问.

In order to be able to run a library which doesn't scale really well in multithreaded environments I have created an object pool to automatically create a limited number of instances so to increase the total throughput. I am using a SemaphoreSlim to lock/unlock access to the underlying instances.

为完整起见,找到在MSDN上.

/// <summary>
/// An object pool with a fixed amount of objects.
/// </summary>
/// <typeparam name="T">The type to have in this pool</typeparam>
public class FixedObjectPool<T> : ObjectPool<T>
    where T : class
{
    private int _maxObjectCount;
    private SemaphoreSlim _objectAvailable;

    public FixedObjectPool(Func<T> objectGenerator, int maxObjectCount) : base(objectGenerator)
    {
        _maxObjectCount = maxObjectCount;
        _objectAvailable = new SemaphoreSlim(0, maxObjectCount);
    }

    public override T GetObject()
    {
        _objectAvailable.Wait(10);
        return base.GetObject();
    }

    public override void PutObject(T item)
    {
        base.PutObject(item);
        _objectAvailable.Release();
    }
}

该类每秒应该被调用数千次.除非指定了超时时间(当前为10ms),否则对 GetObject 方法的调用似乎会死锁.

This class is supposed to be invoked several thousand times each second. Unless a timeout period is specified (currently 10ms), a call to the GetObject method seems to deadlock.

我的2美分是调用代码在被锁定的同一线程上运行,因此信号量没有释放.

My 2 cents are that calling code is running on the same thread which gets locked, therefore the semaphore not being released.

如何通过在此类中进行设计,确保方法调用是在其自己的线程上分派的,目的是通过停止此方法之外的运行代码来确保信号量等待不会死锁?

How can I make sure, by design in this class, that method calls are dispatched on their own threads, with the goal of making sure that semaphore waits do not deadlock by halting running code outside this method?

编辑:根据要求,当前正在使用该池,如下所示;

Upon request, usage of the pool currently happens like in the following block;

Parallel.For(0, 10000, (i) => {
    var instance = pool.GetObject();
    // Do something with said instance
    pool.PutObject(instance);
});

推荐答案

您可以使用初始计数为零的信号量进行初始化:

You initialize your semaphore with an initial count of zero:

_objectAvailable = new SemaphoreSlim(0, maxObjectCount);

这意味着所有调用 Wait 的人都将被阻止,无论他们处于哪个线程.

This means that all who call Wait will block, regardless of what thread they are on.

这篇关于信号量由于停止在自己的线程上运行的代码而陷入僵局的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-23 07:47