c# - ThreadSafety 和静态字段 - 混淆?

标签 c# .net multithreading static field

我读了一些文章并做了一些测试/调查,我认为没有准确的结论(可能由于措辞不正确)

好的。一些调查:

有一个人问this question :

Why are static fields generally considered threadsafe?

好吧,所有的回复者都说:不,他们不是。

埃里克还说:

You have it backwards.Because static fields and methods are likely to be accessed from multiple threads, it is a good programming practice to do the work to ensure that they are threadsafe.

(这与我的说法非常接近,稍后我会在这里提问)

但是我也找到了here汉斯说:

enter image description here

天啊—— this other guy 说:

Re-entrancy is still a problem, though. static is not thread-safe, and even static readonly is not re-entrant-safe.

好吧,我很困惑。

附注我不是在谈论这种情况:

public class A
 {
  public static List<int> LST = new List<int>();
 }

List<> 不是线程安全的,所以我不在乎谁拥有它。但是 ->

让我们看看这个

public class A
 {
  public static int Five=5;
 }

什么这段代码不是线程安全的?

我看不出如何Five不能总是 5 :

enter image description here

据我所知- Five永远不可能是0 (初始值),无论有多少线程访问它,它始终为 5!

现在,我同意如果我正在编写使用此 Five 的代码字段 ,那么我必须注意更改的值!

示例:

if (Five < array.Length) return array[five]; //can throw an IndexOutOfBoundsException if five is modified

对此 - 我同意!

但是(恕我直言)说(通常)静态字段不是线程安全的是不正确的!

它们的用法必须被视为可以通过另一个线程改变。

(此外,显然 - 引用非线程安全对象的静态字段,如 List<> - 肯定不会成为线程安全的)

我在这里想说的是,静态字段对于特定场景不是线程安全的,而且通常不是这样!

问题:

  • 有人可以解释一下吗?我确定我在这里错过了什么(或者我不是?)静态字段不是总是非线程安全的(通常)是真的吗

  • 那这个readonly呢?这使得静态字段线程安全(它所做的一切使它一次性初始化而不重新分配)?它是否使其成为线程安全的? (那么重新进入呢?)

最佳答案

静态变量,并不意味着它是“常量”,它只是意味着它是在编译时静态分配的,而不是在运行时动态分配的。

如果您在启动任何线程之前设置静态变量,然后再也不会更改它,而只是从中读取,那么,根据您代码中逻辑的性质,您永远不会让自己陷入这样的境地在其中您将接触到与非线程安全代码相关的问题。这与说静态变量是线程安全的不同。

之所以称为抢占式线程,是因为线程切换会导致代码执行抢占另一个线程的执行,即使是在写入或读取过程中。换句话说,假设您的静态变量是一个整数,根据体系结构,它可能是 4 个字节或 8 个字节。除非变量被明确声明为原子变量,否则一个线程可以开始读取内存,但在另一个线程抢占它并写入同一个变量之前,它只能读取前 2 个字节。当第一个线程恢复时,它读取剩余的字节,当然,到现在为止,这些字节是不一致的。

关于c# - ThreadSafety 和静态字段 - 混淆?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23800917/

相关文章:

c# - 通过 RestSharp 将 XML 发布为 "application/xml"而不是 "text/xml"

javascript - 如何在我们的网络应用程序中创建我们自己的通知(例如 Facebook)

.net - 您如何组织资源文件?

c++ - C++ 构建器 CreateThread() 中的错误

c# - 标签上的 "Invoke or BeginInvoke cannot be called on a control until"

c# - 类未注册(Windows Phone 8.1 中的 HRESULT : 0x80040154) when BackgroundExecutionManager. RequestAccessAsync 异常

c# - 并发队列.Net : Multithreaded consumer

c# - 控制台应用程序中的异步

c# - Linux (Redhat) 上的 .NET Core 应用程序在用户主目录中创建神秘的 ".net"目录/文件

启动新线程时.NET WPF MissingMethodException