访问共享资源时,通过静态锁进行线程同步
本文关键字:线程 同步 静态 共享资源 访问 | 更新日期: 2023-09-27 18:14:32
我试图修复一个问题,线程同步从两个线程都访问一个资源。在本例中,该资源是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();
}
}
}
为什么不直接访问Monitor的方法来代替lock
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);
}
}
如果您的目标是多次调用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()
现在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);
}
}