c# - Queue.Synchronized 比使用 Lock() 更快吗?

标签 c# multithreading performance .net-3.5 queue

我有一个队列,入队操作将由一个线程执行,而出队操作将由另一个线程执行。不用说,我必须为它实现一些线程安全。

我首先尝试在每次入队/出队之前在队列上使用锁,因为它可以更好地控制锁定机制。它运作良好,但我的好奇心让我测试了更多。

然后我尝试使用 Queue.Synchronized 包装器保持其他一切不变。现在,我不确定它是否属实,但这种方法的性能似乎确实快了一点。

您是否认为,两者之间的性能实际上存在一些差异,还是我只是在想象这里的事情..? :)

最佳答案

请求时Queue.Synchonized你得到一个SynchronizedQueue作为返回,它使用 lockEnqueue 的调用非常少和 Dequeue在内部队列上。因此,性能应该与使用 Queue 相同。并管理为 Enqueue 锁定自己和 Dequeue用你自己的lock .

您确实在想象事物 - 它们应该是相同的。

更新

事实上,当使用 SynchronizedQueue 时您正在添加一个间接层,因为您必须通过包装器方法才能到达它正在管理的内部队列。如果有的话,这应该会稍微减慢速度,因为堆栈上有一个额外的帧需要为每次调用进行管理。天知道内联是否会取消这一点。无论如何 - 它是最小的

更新 2

我现在已经对此进行了基准测试,正如我在之前的更新中预测的那样:

"Queue.Synchronized" is slower than "Queue+lock"

我进行了单线程测试,因为它们都使用相同的锁定技术(即 lock ),因此在“直线”中测试纯开销似乎是合理的。

我的基准测试为 Release 构建生成了以下结果:

Iterations      :10,000,000

Queue+Lock      :539.14ms
Queue+Lock      :540.55ms
Queue+Lock      :539.46ms
Queue+Lock      :540.46ms
Queue+Lock      :539.75ms
SynchonizedQueue:578.67ms
SynchonizedQueue:585.04ms
SynchonizedQueue:580.22ms
SynchonizedQueue:578.35ms
SynchonizedQueue:578.57ms

使用以下代码:

private readonly object _syncObj = new object();

[Test]
public object measure_queue_locking_performance()
{
    const int TestIterations = 5;
    const int Iterations = (10 * 1000 * 1000);

    Action<string, Action> time = (name, test) =>
    {
        for (int i = 0; i < TestIterations; i++)
        {
            TimeSpan elapsed = TimeTest(test, Iterations);
            Console.WriteLine("{0}:{1:F2}ms", name, elapsed.TotalMilliseconds);
        }
    };

    object itemOut, itemIn = new object();
    Queue queue = new Queue();
    Queue syncQueue = Queue.Synchronized(queue);

    Action test1 = () =>
    {
        lock (_syncObj) queue.Enqueue(itemIn);
        lock (_syncObj) itemOut = queue.Dequeue();
    };

    Action test2 = () =>
    {
        syncQueue.Enqueue(itemIn);
        itemOut = syncQueue.Dequeue();
    };

    Console.WriteLine("Iterations:{0:0,0}\r\n", Iterations);
    time("Queue+Lock", test1);
    time("SynchonizedQueue", test2);

    return itemOut;
}

[SuppressMessage("Microsoft.Reliability", "CA2001:AvoidCallingProblematicMethods", MessageId = "System.GC.Collect")]
private static TimeSpan TimeTest(Action action, int iterations)
{
    Action gc = () =>
    {
        GC.Collect();
        GC.WaitForFullGCComplete();
    };

    Action empty = () => { };

    Stopwatch stopwatch1 = Stopwatch.StartNew();

    for (int j = 0; j < iterations; j++)
    {
        empty();
    }

    TimeSpan loopElapsed = stopwatch1.Elapsed;

    gc();
    action(); //JIT
    action(); //Optimize

    Stopwatch stopwatch2 = Stopwatch.StartNew();

    for (int j = 0; j < iterations; j++) action();

    gc();

    TimeSpan testElapsed = stopwatch2.Elapsed;

    return (testElapsed - loopElapsed);
}

关于c# - Queue.Synchronized 比使用 Lock() 更快吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4818202/

相关文章:

c# - TextBlock 文本未在 DataGridCell 中垂直居中

c# - 1064 - 你的 SQL 语法有错误;查看手册

performance - 洗牌时跟踪项目的最佳方式,以及洗牌前它们所在的位置

python - 为什么 defaultdict(int) 的 dicts 使用这么多内存? (以及其他简单的 python 性能问题)

c# - 为什么 SubmitChanges 不起作用?

c# - 特定区域怎么画

java - 使用 foreach 遍历 ArrayList 时的线程安全

python - 阻塞生成器似乎只生成一个值。为什么?

c++ - C++ 中分离线程的资源释放

performance - ARM NEON : Tools to predict performance issues due to memory access limited bandwidth?