如果我确保两个线程永远不会并行运行,我还是要让我的列表变量挥发吗?

5 c# multithreading

想象一下,我有这样的代码,其中里面的Windows窗体计时器我可以生成一些线程-但我保证只有一个线程使用下面的方法(从答案的一个指示运行位置 -马特·约翰逊):

nb:我们现在假设这种_executing方法有效,我不使用backgroundworker等.

private volatile bool _executing;

private void TimerElapsed(object state)
{
    if (_executing)
        return;

    _executing = true;

    if(smth)
    {
    Thread myThread = new Thread(MainThread1);
    myThread.IsBackground = true;
    myThread.Start();

    }else
    {
    Thread myThread = new Thread(MainThread2);
    myThread.IsBackground = true;
    myThread.Start();
    }
}


 public void MainThread1()
 {
   try
   {
     methodWhichAddelementTomyList(); // e.g., inside list.add();
   }
   finally
   {_executing = false;}
 }
 public void MainThread2()
 {
   try
   {
     methodWhichAddelementTomyList(); // e.g., inside list.add();
   }
   finally
   {_executing = false;}
 }
Run Code Online (Sandbox Code Playgroud)

现在我也有List实例变量,你可以看到我从访问MainThread1MainThread2-但因为我的逻辑上面我确保MainThread1MainThread2从未在并行运行,我还是要做出list volatile?我是否可以遇到与缓存列表变量相关的问题?

编辑:这种方法是否也保护我不会并行运行这些线程?(链接问题中的答案有点不同 - 它运行计时器内的工作 - 所以我想仔细检查).

EDIT2:老实说,下面是否应该volatile在我的list对象上应用关键字没有共同意见.这种状况让我很困惑.如此记录的答案仍然受到欢迎; 否则这还没有完全回答

Jeb*_*Jeb 0

这里似乎有两个问题:

\n\n
    \n
  1. 如果您使用两个线程,但它们从不异步运行,那么为什么要使用两个线程呢?只需适当地序列化您的方法,即坚持一个线程。

  2. \n
  3. 但是,如果需要两个线程(例如,允许一个线程继续处理/保持不受阻塞,而另一个线程正在执行某些其他任务):即使您已对此进行编码以确保没有两个线程可以同时访问该列表,为了安全起见,我会添加一个锁定结构,因为列表不是线程安全的。对我来说,这是最简单的。

  4. \n
\n\n

您可以使用线程安全集合来代替,例如System.Collections.Concurrent中的集合之一。否则,您需要同步对列表的所有访问(即:将每个添加调用放在锁中),

\n\n

我个人避免使用 volatile。Albahari对此有一个很好的解释:“易失性关键字确保字段中始终存在最新值。这是不正确的,因为正如我们\xe2\x80\x99所看到的,写入后跟可以重新排序读取。”

\n\n

易失性只是确保两个线程同时看到相同的数据。它根本不会阻止它们交错读取和写入操作。

\n\n

例如:\n声明一个同步对象,例如:

\n\n
private static Object _objectLock = new Object();\n
Run Code Online (Sandbox Code Playgroud)\n\n

methodWhichAddelementTomyList并在您的方法(以及修改列表的其他任何地方)中使用类似的方法,以确保从不同线程对资源进行串行访问:

\n\n
lock(_objectLock)\n{\n    list.Add(object);\n}\n
Run Code Online (Sandbox Code Playgroud)\n