stevenjin 2024-05-05 10:27 采纳率: 97.3%
浏览 6
已结题

c#中mutex锁的作用范围

假如在方法中用了Mutex锁,锁中间又有一个方法。
此时,锁的做范围包括RunData这个方法吧?即需要等RunData()执行完(甚至该方法中又嵌套了方法)才释放锁吧?
如果是异步锁或普通lock,也是一样吗?

mutex.waitOne();
RunData();
mutex.ReleaseMutex();

  • 写回答

4条回答 默认 最新

  • 专家-赤兔[在线] 全栈领域优质创作者 2024-05-05 10:27
    关注

    引自免费微信小程序:皆我百晓生

    在C#中,Mutex(互斥量)是一种同步原语,用于控制多个线程对共享资源的访问。当一个线程获取到互斥量的锁后,其他尝试获取同一互斥量锁的线程将会被阻塞,直到拥有锁的线程释放它。互斥量的锁定作用范围是显式的,取决于你在代码中如何使用它。

    对于你的例子,如果你在某个方法(例如RunData())内部使用了一个Mutex锁,并且确保了正确的锁定和解锁操作,那么锁的确会保护整个RunData()方法内的代码块。这意味着在mutex.WaitOne();之后至mutex.ReleaseMutex();之前的所有代码都会受到互斥量的保护,无论在这个范围内是否调用了其他方法。

    下面是具体的代码示例:

    using System;
    using System.Threading;
    
    class Program
    {
        private Mutex mutex = new Mutex();
    
        public void RunData()
        {
            mutex.WaitOne();
            
            // 这里的代码受到互斥量保护
            Console.WriteLine("Running data in thread: " + Thread.CurrentThread.ManagedThreadId);
            
            // 假设这是一个嵌套的方法
            NestedMethod();
    
            mutex.ReleaseMutex();
        }
    
        private void NestedMethod()
        {
            // 这里同样受到互斥量保护
            Console.WriteLine("Nested method running in thread: " + Thread.CurrentThread.ManagedThreadId);
        }
    
        static void Main(string[] args)
        {
            var program = new Program();
            
            // 启动两个线程同时运行RunData
            var thread1 = new Thread(program.RunData);
            var thread2 = new Thread(program.RunData);
    
            thread1.Start();
            thread2.Start();
    
            thread1.Join();
            thread2.Join();
    
            Console.ReadLine();
        }
    }
    

    在这个例子中,尽管RunData()方法内部调用了另一个方法NestedMethod(),但因为它们都在同一个mutex.WaitOne();mutex.ReleaseMutex();之间,所以它们都处于同一锁的保护之下。这意味着除非拥有锁的线程完成了整个RunData()方法以及其中的任何嵌套方法,否则其他线程不会进入这些受保护的代码区域。

    至于异步锁(通常指的是使用SemaphoreSlimMonitor或其他同步机制实现的异步版本),其原理类似,但是提供了等待锁的异步版本,允许在等待时不会阻塞当前线程。然而,锁的作用范围仍然是由代码决定的,即从获得锁的地方开始,到释放锁的地方结束。例如,使用SemaphoreSlim的一个简单例子:

    using System;
    using System.Threading.Tasks;
    using System.Threading.Semaphores;
    
    class Program
    {
        private SemaphoreSlim semaphore = new SemaphoreSlim(1);  // 初始化为1,表示只有一个线程可以获取锁
    
        public async Task RunDataAsync()
        {
            await semaphore.WaitAsync();  // 异步等待锁
    
            try
            {
                // 这里的代码受到信号量保护
                Console.WriteLine("Running data in thread: " + Thread.CurrentThread.ManagedThreadId);
                
                // 假设这是一个异步方法
                await NestedMethodAsync();
            }
            finally
            {
                semaphore.Release();  // 在finally块中释放锁,确保锁会被正确释放,无论是否有异常抛出
            }
        }
    
        private async Task NestedMethodAsync()
        {
            // 这里同样受到信号量保护
            Console.WriteLine("Nested method running in thread: " + Thread.CurrentThread.ManagedThreadId);
        }
    
        static void Main(string[] args)
        {
            var program = new Program();
            
            // 同样的,启动两个任务同时运行RunDataAsync
            var task1 = program.RunDataAsync();
            var task2 = program.RunDataAsync();
    
            Task.WaitAll(task1, task2);
    
            Console.ReadLine();
        }
    }
    

    在上述异步示例中,虽然WaitAsync()方法是非阻塞的,但锁的作用范围依然相同:只有当RunDataAsync()方法完成并释放信号量时,其他线程才能获取并继续执行。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论 编辑记录
查看更多回答(3条)

报告相同问题?

问题事件

  • 系统已结题 5月13日
  • 已采纳回答 5月5日
  • 创建了问题 5月5日

悬赏问题

  • ¥15 网络分析设施点无法识别
  • ¥15 状态图的并发态问题咨询
  • ¥15 PFC3D,plot
  • ¥15 VAE模型编程报错无法解决
  • ¥100 基于SVM的信息粒化时序回归预测,有偿求解!
  • ¥15 物体组批优化问题-数学建模求解答
  • ¥15 微信原生小程序tabBar编译报错
  • ¥350 麦克风声源定位坐标不准
  • ¥15 apifox与swagger使用
  • ¥15 egg异步请求返回404的问题