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

时间:2014-07-24 14:52:23

标签: c# multithreading

我正在尝试从两个访问一个资源的线程修复线程同步的问题。在此示例中,该资源是Engine

这里有两个开始启动引擎,其中一个线程正在停止它。 目标引擎的最终结果

澄清:我不控制ThreadOne / ThreadTwo中的代码,并且需要同步进入Lifecycle类。

在这个例子中,实现这个目标的最佳方法是什么?

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();
        }
    }
}

3 个答案:

答案 0 :(得分:0)

如果您的目标是多次拨打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()

答案 1 :(得分:0)

Now Lifecycle管理同步

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);
    }
}

答案 2 :(得分:0)

为什么不直接使用Monitor的方法替换lock

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);
    }
}