强制串行单例功能锁
Force Serial Singleton Function Lock
我想要 运行 一个并行进程,该进程的一部分使用线程安全单例。我在 Singleton 中使用 COM Interop,并且在系统范围内一次只能有一个实例 运行ning。
Singleton的操作不能重叠。调用单例操作时,当前不能有任何其他单例操作在进行中..
我有一个简化的工作示例,它使用锁来确保单例操作在多个线程中保持序列化。
有人会推荐比我目前拥有的更优化的解决方案吗?或者我已经实施的是否合适?谢谢。
当前工作示例-
internal class Program
{
static void Main(string[] args)
{
Parallel.ForEach(Enumerable.Range(0, 10), i =>
{
if (i % 2 == 0)
SerializedSingleton.Instance.Serializer(); // Serialized Operation Only
else
Thread.Sleep(100); // Concurrent Operations
});
}
}
public sealed class SerializedSingleton
{
private static readonly object SerializerLock = new object();
// THREAD-SAFE SINGLETON SETUP
private static readonly Lazy<SerializedSingleton> lazy =
new Lazy<SerializedSingleton>(() => new SerializedSingleton());
public static SerializedSingleton Instance { get => lazy.Value; }
private SerializedSingleton()
{
}
public void Serializer()
{
lock (SerializerLock)
{
Console.WriteLine("Serializer START");
Thread.Sleep(2000);
Console.WriteLine("Serializer STOP");
}
}
}
当前输出(期望)-
Serializer START
Serializer STOP
Serializer START
Serializer STOP
Serializer START
Serializer STOP
Serializer START
Serializer STOP
Serializer START
Serializer STOP
需要避免-
Serializer START
Serializer START
Serializer START
Serializer START
Serializer START
Serializer STOP
Serializer STOP
Serializer STOP
Serializer STOP
Serializer STOP
Thead-safe 单例来源:https://csharpindepth.com/Articles/Singleton
无论何时调用 lock (SerializerLock)
和 Thread.Sleep(..)
,都会阻塞当前线程。如果竞争激烈,就会有很多线程在等待锁。这对您的 CPU 有一点影响,并减少了线程池中可用的线程数。另一种方法是使用 SemaphoreSlim
,并使锁定异步:
public sealed class SerializedSingleton
{
// This doesn't need to be static if the instance is a singleton
private readonly SemaphoreSlim serializerLock = new SemaphoreSlim(1, 1);
private static readonly Lazy<SerializedSingleton> lazy =
new Lazy<SerializedSingleton>(() => new SerializedSingleton());
public static SerializedSingleton Instance { get => lazy.Value; }
public async Task SerializerAsync()
{
await serializerLock.WaitAsync();
try
{
Console.WriteLine("Serializer START");
await Task.Delay(2000);
Console.WriteLine("Serializer STOP");
}
finally
{
serializerLock.Release();
}
}
}
我想要 运行 一个并行进程,该进程的一部分使用线程安全单例。我在 Singleton 中使用 COM Interop,并且在系统范围内一次只能有一个实例 运行ning。
Singleton的操作不能重叠。调用单例操作时,当前不能有任何其他单例操作在进行中..
我有一个简化的工作示例,它使用锁来确保单例操作在多个线程中保持序列化。
有人会推荐比我目前拥有的更优化的解决方案吗?或者我已经实施的是否合适?谢谢。
当前工作示例-
internal class Program
{
static void Main(string[] args)
{
Parallel.ForEach(Enumerable.Range(0, 10), i =>
{
if (i % 2 == 0)
SerializedSingleton.Instance.Serializer(); // Serialized Operation Only
else
Thread.Sleep(100); // Concurrent Operations
});
}
}
public sealed class SerializedSingleton
{
private static readonly object SerializerLock = new object();
// THREAD-SAFE SINGLETON SETUP
private static readonly Lazy<SerializedSingleton> lazy =
new Lazy<SerializedSingleton>(() => new SerializedSingleton());
public static SerializedSingleton Instance { get => lazy.Value; }
private SerializedSingleton()
{
}
public void Serializer()
{
lock (SerializerLock)
{
Console.WriteLine("Serializer START");
Thread.Sleep(2000);
Console.WriteLine("Serializer STOP");
}
}
}
当前输出(期望)-
Serializer START
Serializer STOP
Serializer START
Serializer STOP
Serializer START
Serializer STOP
Serializer START
Serializer STOP
Serializer START
Serializer STOP
需要避免-
Serializer START
Serializer START
Serializer START
Serializer START
Serializer START
Serializer STOP
Serializer STOP
Serializer STOP
Serializer STOP
Serializer STOP
Thead-safe 单例来源:https://csharpindepth.com/Articles/Singleton
无论何时调用 lock (SerializerLock)
和 Thread.Sleep(..)
,都会阻塞当前线程。如果竞争激烈,就会有很多线程在等待锁。这对您的 CPU 有一点影响,并减少了线程池中可用的线程数。另一种方法是使用 SemaphoreSlim
,并使锁定异步:
public sealed class SerializedSingleton
{
// This doesn't need to be static if the instance is a singleton
private readonly SemaphoreSlim serializerLock = new SemaphoreSlim(1, 1);
private static readonly Lazy<SerializedSingleton> lazy =
new Lazy<SerializedSingleton>(() => new SerializedSingleton());
public static SerializedSingleton Instance { get => lazy.Value; }
public async Task SerializerAsync()
{
await serializerLock.WaitAsync();
try
{
Console.WriteLine("Serializer START");
await Task.Delay(2000);
Console.WriteLine("Serializer STOP");
}
finally
{
serializerLock.Release();
}
}
}