【问题标题】:Semaphore is deadlocking by halting code running on own thread [duplicate]信号量通过停止在自己的线程上运行的代码而死锁[重复]
【发布时间】:2019-01-31 16:53:33
【问题描述】:

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

为了完整起见,ObjectPool<T> 派生自 here on 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();
    }
}

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

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

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

编辑:根据请求,当前池的使用情况如下块所示;

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

【问题讨论】:

  • 你能告诉我们一些使用池的代码吗?
  • 看起来您的池最初是空的,所以您是否在尝试将它们取出之前向其中添加对象?
  • @Sean 查看更新后的问题。如果池中没有可用的实例,则会即时实例化一个新实例。

标签: c# .net multithreading


【解决方案1】:

您使用初始计数为零来初始化信号量:

_objectAvailable = new SemaphoreSlim(0, maxObjectCount);

这意味着所有调用Wait 的人都会阻塞,无论他们在哪个线程上。

【讨论】:

  • 这太小了……但意义重大。
【解决方案2】:

问题是您将信号量的初始计数设置为零:

_objectAvailable = new SemaphoreSlim(0, maxObjectCount);

这意味着当您调用GetObject 时,将没有任何可用的信息并且信号量将超时。

您的池开始时是空的,因此您需要先将一些东西放入其中。这会增加信号量,也意味着你有一些东西可以得到!

您提到该类在多线程环境中不能很好地扩展,我不确定您的解决方案是否有效。您基本上是在等待信号量,然后通过调用基类来创建对象。当您正确使用信号量时,最终会有多个线程能够同时调用基类,这意味着基类必须是线程安全的。

【讨论】:

  • 你的意思是ObjectPool&lt;T&gt;?因为有一个ConcurrentBag&lt;T&gt;,老实说,我并不担心并发性。我是不是该?在我的例子中,不是线程安全的对象是通用的T
猜你喜欢
  • 2015-03-19
  • 2021-05-09
  • 2023-03-09
  • 1970-01-01
  • 2012-03-20
  • 2013-09-28
  • 2015-09-30
  • 1970-01-01
  • 2011-12-06
相关资源
最近更新 更多