如何确保一部分代码一次只由一个线程运行[重复]

问题描述 投票:-1回答:3

这个问题在这里已有答案:

我的情况是这样的:

  • 我只能访问已在多线程中运行的部分代码,因此我不创建线程,也无法访问创建线程的代码部分
  • 我需要确保相当复杂(调用多个函数,涉及DB访问等)代码的一部分一次只由一个线程执行

所以我的问题是,有可能这样做吗?如果是这样,最好的方法是什么?

以下是我要完成的一些说明性代码:

// This method is executed by multiple threads at the same time
protected override void OnProcessItem()
{
    MyObject myObject = new MyObject();

    // Begin of the code that should be executed only once at a time
    // by each thread

    bool result = myObject.DoComplexStuff();

    if(result == true)
    {
        this.Logger.LogEvent("Write something to log");
        // ... Do more stuff
    }
    else
    {
        this.Logger.LogEvent("Write something else to log");
        // ... Do more stuff
    }

    // ... Do more stuff

    // End of the code that should be executed only once at a time
    // by each thread
}

一些背景

在问这里之前,我做了一个小的调查工作并结束阅读:

https://docs.microsoft.com/en-us/dotnet/standard/threading/overview-of-synchronization-primitives

但我仍然不确定什么是最好的方法或如何在mi场景中实现它。

另外,我不是你想的多线程专家。

c# .net multithreading
3个回答
1
投票

是的,你可以使用lock。在类中创建一个私有同步对象,获取此对象的锁定,一次只有一个线程能够执行lock块中的代码。

class Foo
{ 
    private readonly object syncObj = new object();

     public void Blah()
     {
          lock (syncObj)
          {
              //only one thread at a time
              //will execute this code
          }
     }
 }

2
投票

最简单的方法是放lock,例如:

// static: conservative policy: no two threads in the entire application
// can enter locked block at the same time. 
// You may want to be more lenient and lock, say on this.Logger i.e. 
// no two theards addressing the same Logger... 
private static object syncObject = new object();

...

protected override void OnProcessItem() {
  MyObject myObject = new MyObject();

  // Begin of the code that should be executed only once at a time
  lock (syncObject) {
    bool result = myObject.DoComplexStuff();

    if (result) {
      this.Logger.LogEvent("Write something to log"); 

      // ... Do more stuff
    }
    else {
      this.Logger.LogEvent("Write something else to log");

      // ... Do more stuff
    }

    // ... Do more stuff
  } 
  // End of the code that should be executed only once at a time by each thread
} 

0
投票

我添加了一些关于lock如何工作的评论

private object _OnProcessItemLockObject = new object();
// This method is executed by multiple threads at the same time
protected override void OnProcessItem()
{
    MyObject myObject = new MyObject();

    // Begin of the code that should be executed only once at a time
    // by each thread

    bool result = false;
    lock(_OnProcessItemLockObject)
    {
        //mat: the part inside the lock will only be executed by one thread. All other threads will wait till the lock-object is unlocked.
        result = myObject.DoComplexStuff();
    }

    //mat: the following code will get executed parallel
    if(result == true)
    {
        this.Logger.LogEvent("Write something to log");
        // ... Do more stuff
    }
    else
    {
        this.Logger.LogEvent("Write something else to log");
        // ... Do more stuff
    }

    // ... Do more stuff

    // End of the code that should be executed only once at a time
    // by each thread
}
© www.soinside.com 2019 - 2024. All rights reserved.