C# 编程中互斥锁的使用

C# 中的互斥锁

互斥锁是 C# 中使用的同步原语,用于控制多个线程或进程对共享资源的访问。其目的是确保在任何给定时间只有一个线程或进程可以获取互斥锁,从而提供互斥。

C# 中互斥锁的优点

可以使用互斥锁 (Mutex) 并享受其带来的好处。

1. 共享资源的独占访问

  • 场景:多个线程或进程需要独占访问共享资源(例如文件、数据库或硬件设备)的情况。
  • 示例:考虑一个多线程应用程序,其中多个线程需要同时写入共享日志文件。
  • 好处: 利用互斥锁,可以保证一次只有一个线程或进程可以访问资源,从而防止数据损坏或竞争条件。

2.跨进程同步

  • 场景:不同进程中运行的线程之间需要同步。
  • 示例:协调多个进程对共享内存映射文件的访问。
  • 好处:互斥锁可以被命名并在整个系统范围内使用,从而实现跨进程边界的同步。

3. 关键部分保护

  • 场景:代码的关键部分需要防止被多个线程并发执行的情况。
  • 示例:考虑一个缓存实现,其中添加或删除项目必须是线程安全的。
  • 好处:通过使用互斥锁,它有助于对关键部分的访问进行序列化,确保一次只有一个线程执行受保护的代码,从而避免竞争条件。

4. 资源池化

  • 场景:管理对有限资源池(例如数据库连接或网络套接字)的访问时。
  • 示例:多个线程竞争可用连接的连接池。
  • 好处:可以使用互斥锁 (Mutex) 来控制对池的访问,从而保证同时使用的用户数量不超过池的容量。

5.避免死锁

  • 场景:在多个同步原语一起使用以防止发生死锁的情况下。
  • 示例:实现一个需要原子锁定多个资源的事务系统。
  • 好处:互斥锁可以参与死锁避免策略,有助于防止死锁情况的发生。

互斥锁的实现

步骤1.

使用Xaml View测试所有情况。

<Window x:Class="MutexExample.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:MutexExample"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <StackPanel Orientation="Vertical">
            <Button x:Name="BtnSR" Height="30" Content="Shared Resource" Margin="10" Click="BtnSR_Click"/>
            <Button x:Name="BtnCPS" Height="30" Content="Cross-Process Synchronization" Margin="10" Click="BtnCPS_Click"/>
            <Button x:Name="BtnCSP" Height="30" Content="Critical Section Protection" Margin="10" Click="BtnCSP_Click"/>
            <Button x:Name="BtnRP" Height="30" Content="Resource Pooling" Margin="10" Click="BtnRP_Click"/>
            <Button x:Name="BtnDLA" Height="30" Content="Deadlock Avoidance" Margin="10" Click="BtnDLA_Click"/>
        </StackPanel>
    </Grid>
</Window>

后端编程

using System;
using System.Threading;
using System.Windows;

namespace MutexExample
{
    public partial class MainWindow : Window
    {
        Mutex mutex = new Mutex();
        static int availableResources = 3;

        public MainWindow()
        {
            InitializeComponent();
        }

        private void SharedResourceAccess(object id)
        {
            mutex.WaitOne(); // Acquire the mutex
            try
            {
                Console.WriteLine($"Thread {id} is accessing the shared resource...");
                // Simulate some work
                Thread.Sleep(2000);
            }
            finally
            {
                mutex.ReleaseMutex(); // Release the mutex
            }
        }

        private void BtnSR_Click(object sender, RoutedEventArgs e)
        {
            // Create multiple threads accessing the shared resource
            for (int i = 0; i < 5; i++)
            {
                Thread thread = new Thread(SharedResourceAccess);
                thread.Start(i);
            }
        }

        private void BtnCPS_Click(object sender, RoutedEventArgs e)
        {
            // Acquire the mutex
            if (mutex.WaitOne(TimeSpan.FromSeconds(5)))
            {
                try
                {
                    Console.WriteLine("Process 1 has acquired the mutex.");
                    Console.ReadLine(); // Hold the mutex until Enter is pressed
                }
                finally
                {
                    mutex.ReleaseMutex(); // Release the mutex
                }
            }
            else
            {
                Console.WriteLine("Process 1 failed to acquire the mutex.");
            }
        }

        private void CriticalSectionAccess(object id)
        {
            mutex.WaitOne(); // Acquire the mutex
            try
            {
                Console.WriteLine($"Thread {id} is executing the critical section...");
                // Simulate some work
                Thread.Sleep(2000);
            }
            finally
            {
                mutex.ReleaseMutex(); // Release the mutex
            }
        }

        private void BtnCSP_Click(object sender, RoutedEventArgs e)
        {
            // Create multiple threads accessing a critical section
            for (int i = 0; i < 5; i++)
            {
                Thread thread = new Thread(CriticalSectionAccess);
                thread.Start(i);
            }
        }

        private void ResourceAccess(object id)
        {
            mutex.WaitOne(); // Acquire the mutex
            try
            {
                if (availableResources > 0)
                {
                    availableResources--;
                    Console.WriteLine($"Thread {id} acquired a resource. Remaining resources: {availableResources}");
                    // Simulate some work
                    Thread.Sleep(2000);
                    availableResources++;
                }
                else
                {
                    Console.WriteLine($"Thread {id} could not acquire a resource. No resources available.");
                }
            }
            finally
            {
                mutex.ReleaseMutex(); // Release the mutex
            }
        }

        private void BtnRP_Click(object sender, RoutedEventArgs e)
        {
            // Create multiple threads to access the resource pool
            for (int i = 0; i < 5; i++)
            {
                Thread thread = new Thread(ResourceAccess);
                thread.Start(i);
            }
        }

        private void BtnDLA_Click(object sender, RoutedEventArgs e)
        {
            Thread thread1 = new Thread(Thread1);
            Thread thread2 = new Thread(Thread2);

            thread1.Start();
            thread2.Start();

            thread1.Join();
            thread2.Join();
        }

        private Mutex mutex1 = new Mutex();
        private Mutex mutex2 = new Mutex();

        private void Thread1()
        {
            mutex1.WaitOne();
            Console.WriteLine("Thread 1 acquired mutex1");

            Thread.Sleep(1000);

            mutex2.WaitOne();
            Console.WriteLine("Thread 1 acquired mutex2");

            mutex2.ReleaseMutex();
            mutex1.ReleaseMutex();
        }

        private void Thread2()
        {
            mutex2.WaitOne();
            Console.WriteLine("Thread 2 acquired mutex2");

            Thread.Sleep(1000);

            mutex1.WaitOne();
            Console.WriteLine("Thread 2 acquired mutex1");

            mutex1.ReleaseMutex();
            mutex2.ReleaseMutex();
        }
    }
}
相关推荐
新手unity自用笔记10 小时前
项目-坦克大战学习-子弹的移动与销毁
笔记·学习·c#
qinzechen10 小时前
分享几个做题网站------学习网------工具网;
java·c语言·c++·python·c#
yufei-coder14 小时前
C# Windows 窗体开发基础
vscode·microsoft·c#·visual studio
dangoxiba14 小时前
[Unity Demo]从零开始制作空洞骑士Hollow Knight第十三集:制作小骑士的接触地刺复活机制以及完善地图的可交互对象
游戏·unity·visualstudio·c#·游戏引擎
AitTech14 小时前
深入理解C#中的TimeSpan结构体:创建、访问、计算与格式化
开发语言·数据库·c#
hiyo58518 小时前
C#中虚函数和抽象函数的概念
开发语言·c#
开心工作室_kaic21 小时前
基于微信小程序的校园失物招领系统的设计与实现(论文+源码)_kaic
c语言·javascript·数据库·vue.js·c#·旅游·actionscript
时光追逐者1 天前
WaterCloud:一套基于.NET 8.0 + LayUI的快速开发框架,完全开源免费!
前端·microsoft·开源·c#·.net·layui·.netcore
friklogff1 天前
【C#生态园】打造现代化跨平台应用:深度解析.NET桌面应用工具
开发语言·c#·.net
hiyo5852 天前
C#的面向对象
开发语言·c#