锁定和队列问题(性能)

时间:2009-12-21 15:41:29

标签: c# multithreading locking

今天我得到了here nice answer来解决我的问题。不幸的是,我忘记了如何锁定。

问题很简单 - 在服务器中,每个连接的客户端将获得1到500的唯一ID(可重用),这是客户端的最大值。

答案是创建一个qeue并使用等待元素进行新连接,并在释放时将它们返回。

我不确定我是否理解正确 - 我也应该使用500个元素(整数)初始化qeue并逐一取出它们并在释放后返回?

如果是这样,锁定在这里怎么样?我的问题主要是针对性能,因为我使用了锁。

3 个答案:

答案 0 :(得分:1)

如果您可以使用Parallel Extensions,请转到ConcurrentQueue

如果你不能,你可以找到如何在Herb Sutter的this article中实现你自己的

顺便说一下,Jon Skeet的回答是告诉你只是尝试排队,如果空的生成和使用。当你完成id后,只需将它排入队列即可。没有提到500个ID。如果您需要限制为500个ID,那么您将需要使用500个ID初始化队列,然后在队列为空时,而不是生成新的队列。为此,consumer/producer pattern将更适合。

答案 1 :(得分:0)

我不明白你想做什么。

您可以为已使用的数字填充哈希表。

您可以将其存储在应用程序范围的变量中,并在访问该资源时使用Application.Lock和Application.Unlock方法。

答案 2 :(得分:0)

这样的东西?

/// <summary>
/// Thread safe queue of client ids
/// </summary>
internal class SlotQueue
{
    private readonly AutoResetEvent _event = new AutoResetEvent(false);
    private readonly Queue<int> _items = new Queue<int>();
    private int _waitCount;

    /// <summary>
    /// Initializes a new instance of the <see cref="SlotQueue"/> class.
    /// </summary>
    /// <param name="itemCount">The item count.</param>
    public SlotQueue(int itemCount)
    {
        // Create queue items
        for (int i = 0; i < itemCount; ++i)
            _items.Enqueue(i);
    }

    /// <summary>
    /// Gets number of clients waiting in the queue.
    /// </summary>
    public int QueueSize
    {
        get { return _waitCount; }
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="waitTime">Number of milliseconds to wait for an id</param>
    /// <returns></returns>
    public int Deqeue(int waitTime)
    {
        // Thread safe check if we got any free items
        lock (_items)
        {
            if (_items.Count > 0)
                return _items.Dequeue();
        }

        // Number of waiting clients.
        Interlocked.Increment(ref _waitCount);

        // wait for an item to get enqueued
        // false = timeout
        bool res = _event.WaitOne(waitTime);
        if (!res)
        {
            Interlocked.Decrement(ref _waitCount);
            return -1;
        }

        // try to fetch queued item
        lock (_items)
        {
            if (_items.Count > 0)
            {
                Interlocked.Decrement(ref _waitCount);
                return _items.Dequeue();
            }
        }

        // another thread got the last item between waitOne and the lock.
        Interlocked.Decrement(ref _waitCount);
        return -1;
    }

    /// <summary>
    /// Enqueue a client ID
    /// </summary>
    /// <param name="id">Id to enqueue</param>
    public void Enqueue(int id)
    {
        lock (_items)
        {
            _items.Enqueue(id);
            if (_waitCount > 0)
                _event.Set();
        }
    }
}