c# - 这个逻辑/代码链有什么明显的问题吗?

标签 c# multithreading queue

我正在阅读的一本书是“多处理器编程的艺术”,作者是 Maurice Herlihy 和 Nir ​​Shavit。其中,有一个“无等待”队列(经过一些语言调整)在线程环境中完美地运行测试和逻辑——至少,即使分布在 5 个线程上的 10,000,000 个项目也没有冲突,并且逻辑检查。

(我编辑队列以在无法获取项目时返回 false,而不是抛出异常。代码如下)。

但是,它有一个警告;队列不能增长。粗略的逻辑检查表明它不能在不锁定队列的情况下增长 - 这在某种程度上否定了拥有无锁队列的意义。

那么,目的就是创建一个可以增长的无锁(或者至少是无饥饿锁定)队列。

因此:如果我们基本上以一种不矛盾的方式为每个线程提供他们自己的共享队列(并且接受这个问题已经解决的可能性很高,并且更好地用于边做边学的目的):

        WaitFreeQueue<Queue<int>> queues = new WaitFreeQueue<Queue<int>>(threadCount);

        // Dequeue a queue, enqueue an item, enqueue the queue.

        // Dequeue a queue, dequeue an item, enqueue the queue.

还有免等待队列(以前的代码包含在注释中,以防我进行任何重大更改):

/// <summary>
/// A wait-free queue for use in threaded environments.
/// Significantly adapted from "The Art of Multiprocessor Programming by Maurice Herlihy and Nir Shavit".
/// </summary>
/// <typeparam name="T">The type of item in the queue.</typeparam>
public class WaitFreeQueue<T>
{
    /// <summary>
    /// The index to dequeue from.
    /// </summary>
    protected int head;
    /// <summary>
    /// The index to queue to.
    /// </summary>
    protected int tail;
    /// <summary>
    /// The array to queue in.
    /// </summary>
    protected T[] items;


    /// <summary>
    /// The number of items queued.
    /// </summary>
    public int Count
    {
        get { return tail - head; }
    }


    /// <summary>
    /// Creates a new wait-free queue.
    /// </summary>
    /// <param name="capacity">The capacity of the queue.</param>
    public WaitFreeQueue(int capacity)
    {
        items = new T[capacity];
        head = 0; tail = 0;
    }


    /// <summary>
    /// Attempts to enqueue an item.
    /// </summary>
    /// <param name="value">The item to enqueue.</param>
    /// <returns>Returns false if there was no room in the queue.</returns>
    public bool Enqueue(T value)
    {
        if (tail - head == items.Length)
            // throw new IndexOutOfRangeException();
            return false;
        items[tail % items.Length] = value;
        System.Threading.Interlocked.Increment(ref tail);
        return true;
        // tail++;
    }


    /// <summary>
    /// Attempts to dequeue an item.
    /// </summary>
    /// <param name="r">The variable to dequeue to.</param>
    /// <returns>Returns true if there was an available item to dequeue.</returns>
    public bool Dequeue(out T r)
    {
        if (tail - head == 0)
        // throw new InvalidOperationException("No more items.");
        { r = default(T); return false; }
        r = items[head % items.Length];
        System.Threading.Interlocked.Increment(ref head);
        // head++;
        // return r;
        return true;
    }
}

那么:这行得通吗?如果不是,为什么?如果是这样,是否还有任何可预见的问题?

谢谢。

最佳答案

尝试编写无锁多线程代码很难,你应该把它留给比你或我更了解它的人(并使用例如 ConcurrentQueue<T> ),或者根本不写它(并使用锁),如果可能的话。

话虽如此,您的代码存在几个问题:

  1. 这不是队列。如果threadCount是 2,然后将项目 1、2 和 3 一个接一个地入队,然后出队,得到项目 2!
  2. 你不能先使用一个字段的值,然后再调用Interlocked.Increment()像你一样。想象一下这样的事情:

    1. 在线程 1 上:items[tail % items.Length] = value;
    2. 在线程 2 上:items[tail % items.Length] = value;
    3. 在线程 2 上:Interlocked.Increment(ref head);
    4. 在线程 1 上:Interlocked.Increment(ref head);

    现在,两个线程排队到相同的位置,之后的位置没有改变。这是错误的。

关于c# - 这个逻辑/代码链有什么明显的问题吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6480977/

相关文章:

c# - 如何连接异步枚举?

c# - 如何从网站上的表格中检索数据?

java - Common Lisp 波尔多线程锁相当于 Java 同步吗?

python - 在 Python 中将线程和进程与共享队列一起使用

php - laravel 5 中应用程序 URL 的意义是什么

c# - OOP 接口(interface)和基类

c# - WPF MVVM 父子关系

android - 在 LooperThread 中获取处理程序返回 null

java - Thread.sleep 也阻塞其他线程,在其他方法上工作,以及在同步方法内部调用自身

c++ - OpenCL:循环内核?