【问题标题】:Is it safe to access this variable from multiple threads?从多个线程访问这个变量是否安全?
【发布时间】:2009-09-22 17:45:22
【问题描述】:

我通常会按照以下思路编写代码:

public class MyClass
{
    static bool m_stop = false;

    public static void Main()
    {
        var th = new Thread(DoStuff);

        th.Start();

        Console.ReadLine();

        m_stop = true;

        th.Join();
    }

    private static void DoStuff()
    {
        while( !m_stop )
        {
            // do things here
        }
    }
}

...而且我总是同步对变量 m_stop 的访问,只是出于习惯。我想知道是否真的有必要这样做(假设在 DoStuff() 中运行一个或两个额外的循环不会有任何伤害)。如果代码完全像这样执行,可能发生的最坏情况是什么?我曾考虑过为 m_stop 使用 volatile 关键字,但我不确定是否有必要这样做。有谁知道吗?

【问题讨论】:

    标签: c# thread-safety


    【解决方案1】:

    没有易失性和任何同步,您展示的代码不是线程安全的。一个线程可以更改变量的值,而另一个线程可能永远看到它,永远循环。如果你用一个公共锁同步所有对它的访问,它是线程安全的。

    现在波动性是一个棘手的话题——我以为我直到最近才理解它,但它doesn't mean quite what I thought it did。但是,我很确定只需将变量设置为 volatile 即可满足您的需要。

    对于任何更复杂的事情,我通常会使用完全同步:每次访问共享数据时都取出一个锁。

    【讨论】:

    • 该示例未显示,但 OP 确实声明他们同步访问m_stop。
    • 为了更好地理解 volatile 及其周围的困惑,请阅读 Joe Duffy 的这篇 (bluebytesoftware.com/blog/…) 帖子。真是一本好书。
    • 哎呀......乔恩我迟到了那个链接......没有注意到那个链接。
    • @Andrew:实际上,第三次阅读了这个问题,我原来的答案仍然有用:OP 是在询问 问题中的代码 是否是线程安全的,而不是包含同步的代码。
    • @Jon - 我同意,我认为你的回答也很有用 - 我只是很挑剔:)
    【解决方案2】:

    虽然这种方法在技术上没有任何问题,但当您的应用程序需要扩展时,您可能会遇到麻烦。此外,如果您正在同步访问 m_stop,则无需将其设为 volatile。

    【讨论】:

    • 您的评论与 Jon 的直接矛盾。我不知道谁是对的,但这似乎很重要。如果对 m_stop 的访问未同步,则始终将值传播到其他线程?
    【解决方案3】:

    更新m_stop时必须设置内存屏障。因此您必须将其标记为易失性(或自己放置内存屏障/易失性读写)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-01-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-09-07
      • 1970-01-01
      • 1970-01-01
      • 2014-01-19
      相关资源
      最近更新 更多