xsl*_*xsl 10 c# static multithreading thread-safety
可能重复:
C#自动实现的静态属性是否是线程安全的?
在以下示例类中
static class Shared
{
public static string[] Values { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
许多读者线程Values定期读取字符串数组,而有时单个编写器将使用setter用新值替换整个数组.我需要使用ReaderWriterLock或者这是C#会自动处理的吗?
编辑:在我的情况下,唯一需要的"线程安全性"是:当读者在读者搜索值时替换数组时,不会发生任何错误.我不在乎读者是否会立即使用新值,只要他们将来会使用它
Jef*_*dge 10
这种用法是线程安全的:
string[] localValues = Shared.Values;
for (int index = 0; index < localValues.length; index++)
ProcessValues(localValues[index]);
Run Code Online (Sandbox Code Playgroud)
这种用法不是线程安全的,并且可能导致越界异常:
for (int index = 0; index < Shared.Values.Length; index++)
ProcessValues(Shared.Values[index]);
Run Code Online (Sandbox Code Playgroud)
通过这样做,我宁愿让线程安全调用更自然:
static class Shared
{
private static string[] values;
public static string[] GetValues() { return values; }
public static void SetValues(string[] values) { Shared.values = values; }
}
Run Code Online (Sandbox Code Playgroud)
当然,用户仍然可以将GetValues()置于循环中,并且它会同样糟糕,但至少它显然很糟糕.
根据具体情况,更好的解决方案可能是分发副本,这样调用代码根本不能改变数组.这是我通常会做的,但在您的情况下可能不合适.
static class Shared
{
private static string[] values;
public static string[] GetValues()
{
string[] currentValues = values;
if (currentValues != null)
return (string[])currentValues.Clone();
else
return null;
}
public static void SetValues(string[] values)
{
Shared.values = values;
}
}
Run Code Online (Sandbox Code Playgroud)
无需任何额外的保护,有没有保证,一个读线程将永远看到新的价值.在实践中,只要阅读线程做了重要的事情,它就会看到新值.特别是,你永远不会看到"半"更新,引用指向死区.
如果你进入这个领域volatile,我相信即使这种危险也会被消除 - 但是无锁编程通常很难解释.当然,这意味着放弃它是一个自动实现的属性.
这取决于线程安全的含义.
读取和替换保证是原子的,但不能保证写入后的读取必然会读取新值.
为了回应你的编辑......
没什么不好将与您现有的代码发生(例如,撕裂读取),但不保证您的读者会不断看到新的价值.例如,可能 - 尽管可能不太可能 - 旧的引用将永远缓存在寄存器中.