c# - 锁定并完成所有工作,还是仅在必要时松开并抓取?

标签 c# .net multithreading

这两种选择中哪一种更好?

在循环外锁定?

lock (_workLock)
{
    foreach (var resultObject in getObjectTask.Result)
    {
        foreach (var key in resultObject.Keys)
        {
            string value = resultObject.GetValue(key);
            _lockedObject.DoSomething(key, value);
        }
    }
}

还是仅在访问锁定对象时才锁定?

foreach (var resultObject in getObjectTask.Result)
{
    foreach (var key in resultObject.Keys)
    {
        string value = resultObject.GetValue(key);
        lock (_workLock)
            _lockedObject.DoSomething(key, value);
    }
}

可能有 5-10 个并发操作想要大致同时执行此操作。这是周围的代码:

var tasks =
    from provider in _objectProviders
    select Task.Factory.StartNew(() => provider.Objects)
        .ContinueWith(getObjectTask =>
        {
            // One of the operation bodies from above would go here
        });

var taskList = Task.WhenAll(tasks);
taskList.Wait();

// Use results from operations here

编辑:这不是真正的答案,所以我没有将其作为答案发布,但是在评论部分输入之后,我重构了我的代码,现在我根本不再需要锁了:

var tasks =
    (from provider in _objectProviders
    select Task.Factory.StartNew(() => provider.Objects)).ToList();

while (tasks.Count > 0)
{
    int completedTask = Task.WaitAny(tasks.ToArray<Task>());
    var task = tasks[completedTask];
    var objects = task.Result;

    foreach (var resultObject in objects)
    {
        foreach (var key in resultObject.Keys)
        {
            string value = resultObject.GetValue(key);
            _unlockedObject.DoSomething(key, value);
        }
    }

    tasks.RemoveAt(completedTask);
}

最佳答案

视情况而定!

哪个更好 100% 取决于您的任务在做什么。

在循环内获取锁意味着您要浪费大量时间来获取和释放锁。但是,如果您的大部分时间都花在做非锁定并行事情上,它可以释放足够多的锁以获得更多并行性。

在循环顶部获取锁会阻止并行性,但会节省锁定,这与您的操作相比可能代价高昂。

所有你能做的就是看看你的分析器,找出最适合你的情况。作为引用,如果没有争用,现代硬件上的锁需要大约 100-150 次操作才能锁定/解锁(这是粗略的经验法则,而不是硬设置值)。

考虑第三种选择,它是两者的混合体:执行所有并行操作,然后批量处理串行操作。也许每 10 个对象,捕获锁并快速完成所有的串行工作。这让您可以两全其美

关于c# - 锁定并完成所有工作,还是仅在必要时松开并抓取?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25933832/

相关文章:

C# 聚合列表中的属性

c# - 如何通过分析 API(ICofProfilerInfo 或任何 IMetadataImport 或任何其他方式)读取 System.Threading.Thread.ThreadState

c# - 二进制模式比较快捷方式/C# 中最快的实现

c# - 线程安全的数据缓冲区,以进行大小受控的批量插入

.net - 基于规则/限制返回对象列表的算法

python - 我的脚本需要同时运行两个循环来读取来自两个不同来源的 IO 数据。我的线程正确吗?

c++ - 如何提高多线程效率?

c# - Xamarin IOS : Task delay issue

.net - 如何使用 .NET 2 System.Configuration.Install 检测更新?

Java - Java 线程可以多次调用启动吗?