【问题标题】:checking condition fails when using threading使用线程时检查条件失败
【发布时间】:2015-06-14 21:43:30
【问题描述】:

我在我的应用程序中使用线程

我正在创建一个文件夹,但该文件夹尚不存在

if (!ExistingFolders.Contains(currentFolder)){
    if (lastCreatedFolder != folder) {
             lastCreatedFolder = folder;
             CreateNewFolder(context, siteLink, lName, fName);
                                }
                          }

当有 5 个线程并行运行时,这种情况是行不通的!! 例如,所有 5 个线程都试图创建一个名为“New”的文件夹 第一个正在创建,而其余的则抛出“文件夹已存在”错误,因为它已经创建了

在这种情况下如何检查情况?

这里所有 5 个线程都在并行运行,并且条件对于所有情况都为真,而只有第一种情况应该为真

【问题讨论】:

  • 你有什么问题?
  • 这是一个众所周知的问题。只需处理错误。
  • 为什么线程需要创建文件夹。在主线程中创建它,并在线程执行终止后,如果它无用则将其删除。您正在将完美的同步 io 操作推送到多个线程,并通过使用锁定来解决他们不想解决的问题来显着降低它们的性能。在您的架构中找到一种方法来尽可能避免锁定。

标签: c# .net multithreading


【解决方案1】:

这是一种竞争条件,您必须使用同步机制来修复它。例如,通过使用 lock 关键字,您可以确保代码范围一次只能由一个线程访问。这里 lockobject 是在这些操作之前创建的对象。例如readonly const 很常见。

lock(lockobject){

if (!ExistingFolders.Contains(currentFolder)){
    if (lastCreatedFolder != folder) {
             lastCreatedFolder = folder;
             CreateNewFolder(context, siteLink, lName, fName);
                                }
                          }
}

【讨论】:

  • 但它仍然可能发生,其他进程也可以做到。这使它成为一个不太常见的错误,但它仍然必须处理。
  • 是的,确实如此。我们无法避免这种例外。甚至我的 Windows 资源管理器也有这个问题
【解决方案2】:

在这种情况下如何检查情况?

通过使用同步原语,例如lock

public readonly object syncRoot = new object();

lock (syncRoot)
{
    if (!ExistingFolders.Contains(currentFolder))
    {
        if (lastCreatedFolder != folder) 
        {
            lastCreatedFolder = folder;
            CreateNewFolder(context, siteLink, lName, fName);
        }
    }
}

这样,只有第一个到达lock 语句的线程会持有锁,而所有其他线程都等待他释放它。完成后,所有其他线程将看到该文件夹​​已创建。

请注意,如果每个线程正在访问包含锁的类的不同实例,则应将其设为static

【讨论】:

    猜你喜欢
    • 2023-03-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-10
    • 2022-07-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多