强制串行单例功能锁

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