c#多线程之间的排他锁的实现

yizhihongxing

当多个线程同时访问共享数据时,就会出现竞态条件(race condition)。这时候我们就需要使用“锁机制”(lock mechanism)来防止多个线程同时访问共享数据,保证线程安全性。其中一个经典的锁机制就是“排他锁”(exclusive lock),也称为“互斥锁”(mutex)。

下面是c#多线程中排他锁实现的攻略:

一、排他锁的概念

排他锁即互斥锁(mutex),是一种用于保护共享资源,防止在同一时间访问同一个资源的锁。基本原则是:在同一时间只允许一个线程访问共享资源。

二、c#中排他锁的实现

在c#中,排他锁由System.Threading.Mutex类实现。该类提供了一个构造函数Mutex(bool initialValue)和两个方法WaitOne()ReleaseMutex()来实现互斥访问。

2.1 Mutex构造函数

Mutex(bool initialValue):创建一个Mutex实例,并且通过initialValue参数指定初始值。initialValue为true则当前线程拥有Mutex,否则Mutex为空闲状态。

示例代码:

Mutex mutex = new Mutex(false); //初始值为false

2.2 WaitOne()方法

WaitOne():线程试图获取Mutex,如果Mutex未被占用,该线程将拥有Mutex并进入运行状态。如果Mutex已被占用,则该线程将等待,直到其它线程释放Mutex。

示例代码:

mutex.WaitOne();
// 线程执行操作
mutex.ReleaseMutex();

2.3 ReleaseMutex()方法

ReleaseMutex():释放Mutex。

示例代码:

mutex.ReleaseMutex();

三、实例说明

3.1 简单实例

下面是一个简单的示例,展示Mutex的基本使用流程。

class MutexDemo
{
    static Mutex mutex = new Mutex();

    static void Main(string[] args)
    {
        for (int i = 0; i < 5; i++)
        {
            Thread t = new Thread(Print);
            t.Start();
        }

        Console.ReadKey();
    }

    static void Print()
    {
        mutex.WaitOne();
        Console.WriteLine($"线程{Thread.CurrentThread.ManagedThreadId}: 进入");
        Thread.Sleep(1000);
        Console.WriteLine($"线程{Thread.CurrentThread.ManagedThreadId}: 退出");
        mutex.ReleaseMutex();
    }
}

上面的代码中,我们创建了一个Mutex实例,然后创建了5个线程,在每个线程中调用WaitOne()方法获取Mutex,执行一些操作,最后释放Mutex。

输出示例:

线程4: 进入
线程4: 退出
线程3: 进入
线程3: 退出
线程5: 进入
线程5: 退出
线程6: 进入
线程6: 退出
线程7: 进入
线程7: 退出

可以看出,每个线程都互斥地获取了Mutex,并且按照顺序执行,保证了线程安全性。

3.2 使用Mutex实现自旋锁

Mutex还可以用于实现自旋锁(spin lock),即不断检测共享资源是否可用,不可用则一直等待。这种锁适用于共享资源被持有的时间较短的场景。

下面是自旋锁示例代码:

class SpinLockDemo
{
    static Mutex mutex = new Mutex();

    static void Main(string[] args)
    {
        for (int i = 0; i < 5; i++)
        {
            Thread t = new Thread(SpinLock);
            t.Start();
        }

        Console.ReadKey();
    }

    static void SpinLock()
    {
        bool lockTaken = false;
        while (!lockTaken)
        {
            lockTaken = mutex.WaitOne(500);
            if (!lockTaken)
                Console.WriteLine($"线程{Thread.CurrentThread.ManagedThreadId}: 等待");
            else
            {
                Console.WriteLine($"线程{Thread.CurrentThread.ManagedThreadId}: 进入");
                Thread.Sleep(1000);
                Console.WriteLine($"线程{Thread.CurrentThread.ManagedThreadId}: 退出");
                mutex.ReleaseMutex();
            }
        }
    }
}

上面的代码中,我们不断通过循环调用WaitOne()方法检查Mutex是否可用。如果Mutex不可用,则线程进入等待状态;如果Mutex可用,则获取Mutex,并执行一些操作,最后释放Mutex。

输出示例:

线程4: 进入
线程4: 退出
线程3: 等待
线程5: 等待
线程6: 等待
线程7: 等待
线程3: 等待
线程5: 进入
线程5: 退出
线程6: 等待
线程7: 进入
线程7: 退出
线程6: 等待
线程3: 进入
线程3: 退出

可以看出,在Mutex被释放后,其它线程才有机会获取Mutex,保证了线程安全性。同时,Mutex的获取都是互斥的,保证了共享资源的一致性。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:c#多线程之间的排他锁的实现 - Python技术站

(0)
上一篇 2023年6月6日
下一篇 2023年6月6日

相关文章

  • ASP.NET Core依赖注入系列教程之服务的注册与提供

    ASP.NET Core依赖注入系列教程之服务的注册与提供攻略 在ASP.NET Core应用程序中,依赖注入是一种常用的设计模式,用于管理应用程序中的对象和服务。本攻略将介绍如何在ASP.NET Core应用程序中注册和提供服务。 步骤 以下是注册和提供服务的步骤: 创建服务类。 创建一个服务类,该类将提供应用程序所需的服务。例如: public inte…

    C# 2023年5月17日
    00
  • 深入浅析C# 11 对 ref 和 struct 的改进

    深入浅析C# 11 对 ref 和 struct 的改进 简介 C# 11 是微软新推出的一项编程语言的更新版本,其中包含了对于 ref 和 struct 的一些优化改进。此次改进旨在提高代码的运行效率并降低代码运行的堆内存的占用。为了能够更好地理解这些改进,需要先了解 ref 和 struct 的相关知识。 ref 和 struct 在 C# 中,ref …

    C# 2023年6月6日
    00
  • 在C#的类或结构中重写ToString方法的用法简介

    C#中的类和结构体都继承了Object类,而Object类中有一个ToString方法,用于将对象转换为字符串。但是,由于Object类中的ToString方法返回对象类型的名称,而不是对象本身的有用信息,因此我们可能希望在自己的类中重写ToString方法以提供更有用的文本表示。 以下是在C#中重写ToString方法的用法简介: 重写ToString方法…

    C# 2023年6月7日
    00
  • C#通过PInvoke调用c++函数的备忘录的实例详解

    C#通过PInvoke调用C++函数的备忘录 什么是PInvoke PInvoke是Platform Invoke的缩写,是.NET Framework提供给C#程序员调用非托管DLL(Dynamic Link Library)在 Windows 平台上的接口技术。PInvoke 提供的主要技术便是 Marshal 类,Marshal 类可以完成 数据类型 …

    C# 2023年6月7日
    00
  • Java和C#下的参数验证方法

    下面是Java和C#下的参数验证方法的完整攻略: Java下的参数验证方法 在Java中,参数验证通常使用JSR 303/349 Bean Validation规范的注解实现。通过在实体类的属性上标注对应的注解,可以对参数进行各种验证,比如非空、长度、格式等等。这些注解在Java Bean Validation API中已经定义好了。 下面是示例代码: im…

    C# 2023年6月6日
    00
  • C# 文字代码页 文字编码的代码页名称速查表

    C# 文字代码页指的是一种将文本编码成一系列数字(即字符编码)的方式,以便在像计算机中这样的设备上存储和处理文本数据。其中,文字编码的代码页名称速查表,简称编码表,是用于查找不同的编码方式和对应字符的表格。 C# 中常用的编码表有 ANSI、UTF-8、UTF-16 和 UTF-32。下面分别介绍它们的特点及示例说明。 ANSI 编码表 ANSI 编码表是美…

    C# 2023年5月31日
    00
  • 解决WCF不能直接序列化SqlParameter类型的问题

    为了解决WCF不能直接序列化 SqlParameter 类型的问题,可以采用以下步骤: 1. 自定义 DataContractResolver SqlParameter 类型不能被WCF直接序列化,需要自定义 DataContractResolver 以解决该问题。在自定义 DataContractResolver 的过程中,需要使用一些类来处理实际的序列化…

    C# 2023年5月15日
    00
  • c#判断网络连接状态

    下面是“c#判断网络连接状态”的完整攻略 检测网络连接状态 在 C# 中检测网络连接状态,可以通过检查本机与 Internet 之间是否能够互相访问来实现。 实现该功能,可以通过以下几步完成: 第一步:引入命名空间 在代码文件的顶部,引入 System.Net.NetworkInformation 命名空间。该命名空间包含用于检测网络状态的类。 using …

    C# 2023年5月15日
    00
合作推广
合作推广
分享本页
返回顶部