MST
星途 面试题库

面试题:C#中信号量与互斥锁在多线程场景下的应用区别

请阐述在C#多线程编程环境中,信号量(Semaphore或SemaphoreSlim)与互斥锁(Mutex)在应用场景上有哪些主要区别,并举例说明在何种情况下应优先选择使用信号量,何种情况下应优先选择互斥锁。
35.5万 热度难度
编程语言C#

知识考点

AI 面试

面试题答案

一键面试

区别

  1. 资源访问数量限制
    • 信号量:可控制同时访问某一资源或代码段的线程数量,允许多个线程同时进入临界区。例如Semaphore可设置初始信号量数量,SemaphoreSlim更是轻量级,适合高频率信号量操作场景。
    • 互斥锁:同一时间只允许一个线程进入临界区,用于保护共享资源不被多个线程同时访问。
  2. 线程所有权
    • 信号量:不具有线程所有权概念,任何线程获取信号量后,其他线程都可尝试获取。
    • 互斥锁:获取锁的线程拥有该锁,只有拥有锁的线程才能释放它,避免其他线程意外释放。
  3. 跨进程使用
    • 信号量:可用于进程间同步,能在不同进程中共享资源访问控制。
    • 互斥锁:主要用于同一进程内线程间同步,虽然也能跨进程,但使用场景相对较少。

应用场景举例

  1. 优先选择信号量
    • 场景:如数据库连接池场景,假设连接池有10个连接,同时允许10个线程获取连接进行数据库操作。
    • 代码示例
using System;
using System.Threading;

class Program
{
    private static SemaphoreSlim _semaphore = new SemaphoreSlim(10, 10);

    static void Main()
    {
        for (int i = 0; i < 20; i++)
        {
            new Thread(AccessDatabase).Start();
        }
        Console.ReadKey();
    }

    static void AccessDatabase()
    {
        _semaphore.Wait();
        try
        {
            Console.WriteLine($"{Thread.CurrentThread.ManagedThreadId} 获取到连接,开始操作数据库");
            Thread.Sleep(1000);
            Console.WriteLine($"{Thread.CurrentThread.ManagedThreadId} 操作数据库完成,释放连接");
        }
        finally
        {
            _semaphore.Release();
        }
    }
}
  1. 优先选择互斥锁
    • 场景:例如单例模式下,确保全局只有一个实例被创建,在创建实例过程中使用互斥锁防止多个线程同时创建实例。
    • 代码示例
using System;
using System.Threading;

class Singleton
{
    private static Singleton _instance;
    private static Mutex _mutex = new Mutex();

    private Singleton() { }

    public static Singleton GetInstance()
    {
        _mutex.WaitOne();
        try
        {
            if (_instance == null)
            {
                _instance = new Singleton();
            }
            return _instance;
        }
        finally
        {
            _mutex.ReleaseMutex();
        }
    }
}