代码之家  ›  专栏  ›  技术社区  ›  Manuel Navarro

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

  •  -1
  • Manuel Navarro  · 技术社区  · 7 年前

    我的情况是:

    • 我只能访问已经在多线程中运行的部分代码,因此我没有创建线程,也无法访问正在创建线程的部分代码
    • 我需要确保相当复杂的代码部分(调用多个函数,涉及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场景中实现它。

    此外,正如您可能猜到的那样,我并不擅长多线程。

    3 回复  |  直到 7 年前
        1
  •  2
  •   Dmitrii Bychenko    7 年前

    最简单的方法是 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
    } 
    
        2
  •  1
  •   InBetween    7 年前

    是的,您可以使用 lock 为了这个。在类中创建一个私有同步对象,获取该对象上的锁,一次只有一个线程能够在

    class Foo
    { 
        private readonly object syncObj = new object();
    
         public void Blah()
         {
              lock (syncObj)
              {
                  //only one thread at a time
                  //will execute this code
              }
         }
     }
    
        3
  •  0
  •   Mat    7 年前

    我已经添加了一些关于如何 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
    }