Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 访问共享资源时通过静态锁进行线程同步_C#_Multithreading - Fatal编程技术网

C# 访问共享资源时通过静态锁进行线程同步

C# 访问共享资源时通过静态锁进行线程同步,c#,multithreading,C#,Multithreading,我正在尝试修复两个线程的线程同步问题,这两个线程都访问一个资源。在本例中,该资源是引擎 在这里,两次启动正在启动引擎,一个线程正在停止它。目标是获得发动机启动的最终结果 澄清:我不控制ThreadOne/ThreadTwo中的代码,需要在生命周期类中进行同步 在本例中,实现这一点的最佳方法是什么 using System; using System.Threading; class Program { static void Main(string[] args) {

我正在尝试修复两个线程的线程同步问题,这两个线程都访问一个资源。在本例中,该资源是
引擎

在这里,两次启动正在启动引擎,一个线程正在停止它。目标是获得发动机启动的最终结果

澄清:我不控制ThreadOne/ThreadTwo中的代码,需要在
生命周期
类中进行同步

在本例中,实现这一点的最佳方法是什么

using System;
using System.Threading;

class Program
{
    static void Main(string[] args)
    {
        new Thread(ThreadOne).Start();
        new Thread(ThreadTwo).Start();

        Console.Read();
    }

    private static void ThreadOne(object obj)
    {
        Lifecycle.Start();
        Thread.Sleep(500);
        Lifecycle.Stop();
    }

    private static void ThreadTwo(object obj)
    {
        Thread.Sleep(600);
        Lifecycle.Start();
    }
}

class Engine
{
    public void Start()
    {
        Console.WriteLine("Engine was started");
    }

    public void Stop()
    {
        Console.WriteLine("Engine was stopped");
    }
}

static class Lifecycle
{
    private static readonly object LockObject;
    private static Engine Engine;

    static Lifecycle()
    {
        LockObject = new object();
        Engine = new Engine();
    }

    public static void Start()
    {
        lock (LockObject)
        {
            Engine.Start();
            Thread.Sleep(800);
        }
    }

    public static void Stop()
    {
        lock (LockObject)
        {
            Engine.Stop();
        }
    }
}

如果您的目标是多次调用
Start
,而实际上没有第二次启动,那么

private static bool _isStarted

public static void Start()
{
   if(!_isStarted)
   {
       _isStarted = true;
       ...
   }
}

// set to false in Stop()
这有一个竞争条件问题。我用简单变量给出了一个想法

如果你的目标是调用上一个,那么它就是这样实现的:

static int _counter;

// thread 1
Interlocked.Increment(ref _counter); // instead of start
... // sleep?
Incterlocked.Decrement(ref _counter); // instead of stop

// thread 2
Interlocked.Increment(ref _counter); // instead of start
... // sleep?

// after all threads are finished, check _counter
// positive - means Start()

现在,生命周期管理同步

using System;
using System.Threading;

class Program
{
    static void Main(string[] args)
    {
        new Thread(ThreadOne).Start();
        new Thread(ThreadTwo).Start();

        Console.Read();
    }

    private static void ThreadOne(object obj)
    {
        Lifecycle.Start();
        Thread.Sleep(500);
        Lifecycle.Stop();
    }

    private static void ThreadTwo(object obj)
    {
        Thread.Sleep(600);
        Lifecycle.Start();
    }
}

class Engine
{
    public void Start()
    {
        Console.WriteLine("{0:O} [{1}] Engine was started", DateTime.Now, Thread.CurrentThread.ManagedThreadId);
    }

    public void Stop()
    {
        Console.WriteLine("{0:O} [{1}] Engine was stopped", DateTime.Now, Thread.CurrentThread.ManagedThreadId);
    }
}

static class Lifecycle
{
    private static Engine Engine;

    static Lifecycle()
    {
        Engine = new Engine();
    }

    public static void Start()
    {
        Monitor.Enter(Engine);
        Engine.Start();
        Thread.Sleep(800);
    }

    public static void Stop()
    {
        Engine.Stop();
        Monitor.Exit(Engine);
    }
}

为什么不直接访问监视器的方法来代替
s

internal static class Lifecycle
{
    private static Engine Engine;

    static Lifecycle()
    {
        Engine = new Engine();
    }

    public static void Start()
    {
        Monitor.Enter(Engine);
        Engine.Start();
        Thread.Sleep(800);
    }

    public static void Stop()
    {
        Engine.Stop();
        Monitor.Exit(Engine);
    }
}

您希望最后发生的事情是线程2启动引擎?但是,在线程1执行
Stop
方法之前,线程2可以运行
Start
。@YuvalItzchakov是的,它是。在本例中,它将启动发动机两次,然后停止发动机一次。你希望所有的动作都按顺序进行,而不是从外观上开始、停止、开始。在您的程序中,从来没有任何一个时间点,每个线程都应该同时执行某些操作,也不希望任何操作相互交织。因此,解决方案显然是删除所有附加线程,然后按顺序运行程序。您添加了大量线程开销,实际上没有任何好处。谢谢大家,您的答案,特别是删除的答案非常有用。不,目标是执行Start、Stop、Start,而不遗漏任何一项。我现在不知道您需要什么。在本例中,您在注释中说
,它将启动发动机两次,然后停止发动机一次。而不是开始,停止,开始
,这让我觉得你是在用不必要的电话来应付日常开支。但是现在你声明你不想错过电话。你想让他们排队还是什么?@scott4dev-当然,你可以锁定
生命周期
类型。但是,如果您出于某种原因需要多个锁,您不会希望这样做。@ChristopherCurrens MSFT他不建议您锁定
生命周期。那是个糟糕的主意。他建议锁上
引擎
,这很不一样。@Servy-谢谢,直到我看不懂为止。这更有意义,我看不出有多少人建议锁定类型(获得死锁情况的简单方法)。@christorcurrens MSFT现在您的解决方案与我的相同,您可以发布它later@scott4dev-我帮不了你(甚至不能删除它,因为它被标记为答案)。让OP替你做个记号。这些要点对我来说没有任何意义。