gpt4 book ai didi

c# - 线程安全 : Lock vs Reference

转载 作者:太空狗 更新时间:2023-10-29 22:58:54 24 4
gpt4 key购买 nike

我有一个 C# 程序,它有一个在不同线程中写入和读取的列表。写入是用户发起的,可以在任何随机时间点更改数据。读取在一个恒定的循环中运行。读取在任何给定循环中是否丢失数据并不重要,只要它接收到的数据有效并且它在未来的循环中获取新数据即可。

在考虑了 ConcurrentBag 之后,出于各种原因(简单性是其中之一),我决定使用锁。实现锁后,同事跟我说,用临时引用指向内存中的旧List也可以,但我担心如果新赋值和引用赋值同时发生会怎样.

问:下面的临时引用例子线程安全吗?

更新:用户输入提供了在 DoStuff() 中使用的字符串列表。您可以将这些字符串视为常量的定义,因此需要为将来的循环保留这些字符串。它们不会在 DoStuff() 中被删除,只会被读取。 UserInputHandler 是唯一会更改此列表的线程,而 DoStuff() 是唯一会从此列表读取的线程。没有其他人可以访问它。

此外,我知道 Concurrent 命名空间,并在其他项目中使用了其中的大部分集合,但是,我选择不在这里使用它们,因为它们添加了额外的代码复杂性(即 ConcurrentBag 不有一个简单的 Clear() 函数等)。在这种情况下,一个简单的锁就足够了。问题只是下面的第二个例子是否是线程安全的。


锁定

static List<string> constants = new List<string>();

//Thread A
public void UserInputHandler(List<string> userProvidedConstants)
{
lock(items)
{
items.Clear();
foreach(var constant in userProvidedConstants)
{
constants.Add(constant);
}
}
}

//Thread B
public void DoStuff()
{
lock(items)
{
//Do read only actions with items here
foreach(var constant in constants)
{
//readonly actions
}
}
}

引用

static List<string> constants = new List<string>();

//Thread A
public void UserInputHandler(List<string> userProvidedConstants)
{
lock(items)
{
items = new List<string>();
foreach(var constant in userProvidedConstants)
{
constants.Add(constant);
}
}
}

//Thread B
public void DoStuff()
{
var constantsReference = constants;

//Do read only actions with constantsReference here
foreach(var constant in constantsReference)
{
//readonly actions
}
}

最佳答案

没有锁就不安全了。在这种情况下,复制对列表的引用并没有真正为您做任何事情。您当前正在迭代的列表仍有可能在您迭代时在另一个线程中发生变异,从而导致各种可能的不良情况。

关于c# - 线程安全 : Lock vs Reference,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24088662/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com