C#中的lock、Monitor、Mutex学习笔记

C#中的Lock、Monitor、Mutex学习笔记

前言

在多线程并发编程中,由于多线程同时执行,并且对共享资源进行访问时需要考虑线程安全,保证线程的执行顺序或者互斥访问,C#提供了三种方式来处理线程同步问题:Lock、Monitor、Mutex。

在本篇学习笔记中,我们将对这三种方式进行全面的讲解。

Lock

Lock是一种轻量级的同步方式,它是由.NET CLR提供的。Lock通过访问内部运行时环境中的Monitor实现,Monitor又是基于一个非常简单的信号机制,在获取锁之后,需要主动释放锁,不释放锁会导致其他线程无法访问同步锁相关资源。

下面是一个使用Lock的示例:

class Program
{
    static void Main(string[] args)
    {
        object lockObject = new object();

        int sum = 0;
        for (int i = 0; i < 5; i++)
        {
            Thread t = new Thread(() =>
            {
                lock (lockObject)
                {
                    for (int j = 0; j < 100; j++)
                    {
                        sum++;
                    }
                }
            });
            t.Start();
        }

        Console.WriteLine($"The result is: {sum}"); // 输出结果未知
        Console.ReadKey();
    }
}

在上面的代码中,我们创建了一个包含5个线程,每个线程都会对sum进行自增操作,但是在多个线程同时修改一个变量时,会产生数据不一致的问题。

这种情况下,我们可以使用lock来限制只有一个线程能够访问该变量:

class Program
{
    static void Main(string[] args)
    {
        object lockObject = new object();

        int sum = 0;
        for (int i = 0; i < 5; i++)
        {
            Thread t = new Thread(() =>
            {
                lock (lockObject)
                {
                    for (int j = 0; j < 100; j++)
                    {
                        sum++;
                    }
                }
            });
            t.Start();
            t.Join(); // 可以确保线程按顺序执行
        }

        Console.WriteLine($"The result is: {sum}"); // 输出500
        Console.ReadKey();
    }
}

在上面的代码中,我们使用lock限制对sum的访问,只有一个线程可以访问该变量。由于线程执行的速度非常快,所以我们需要使用Join方法等待线程执行完毕,以确保sum的值是正确的。

Monitor

Monitor和Lock的工作机制类似,都是使用一个关键字来锁定代码块。但是,Monitor在使用时需要手动调用Acquire和Release方法来控制临界区以提高代码执行效率。

下面是一个使用Monitor的示例:

class Program
{
    static void Main(string[] args)
    {
        object lockObject = new object();

        int sum = 0;
        for (int i = 0; i < 5; i++)
        {
            Thread t = new Thread(() =>
            {
                Monitor.Enter(lockObject);
                try
                {
                    for (int j = 0; j < 100; j++)
                    {
                        sum++;
                    }
                }
                finally
                {
                    Monitor.Exit(lockObject);
                }
            });
            t.Start();
            t.Join(); // 可以确保线程按顺序执行
        }

        Console.WriteLine($"The result is: {sum}"); // 输出500
        Console.ReadKey();
    }
}

在上面的代码中,我们使用了Monitor.EnterMonitor.Exit方法来代替Lock来控制访问变量的行为。

Mutex

Mutex是一种类似于Lock的同步方式,但是它可以跨进程使用。Mutex可以自动识别持有锁的线程,也可以被释放锁的线程重新获得锁,可以用于跨进程协作和同步。

下面是一个使用Mutex的示例:

class Program
{
    static void Main(string[] args)
    {
        Mutex mutex = new Mutex();
        int sum = 0;
        for (int i = 0; i < 5; i++)
        {
            Thread t = new Thread(() =>
            {
                mutex.WaitOne();
                try
                {
                    for (int j = 0; j < 100; j++)
                    {
                        sum++;
                    }
                }
                finally
                {
                    mutex.ReleaseMutex();
                }
            });
            t.Start();
            t.Join(); // 可以确保线程按顺序执行
        }

        Console.WriteLine($"The result is: {sum}"); // 输出500
        Console.ReadKey();
    }
}

在上面的代码中,我们使用了Mutex来实现同步,保证多个线程对变量的访问是单一的,并且可以被多个进程同时使用。

总结

在多线程并发编程中,使用Lock、Monitor、Mutex来同步访问共享资源是必不可少的技术。在使用时需要注意线程访问顺序以及锁的释放,以保证代码的正确性与效率。

本文对Lock、Monitor、Mutex的使用进行了详细的介绍,并提供了示例代码,希望读者能够理解并熟练掌握该技术。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C#中的lock、Monitor、Mutex学习笔记 - Python技术站

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

相关文章

  • C# dump系统lsass内存和sam注册表详细

    首先我们需要了解一下“C#dump系统lsass内存和sam注册表详细”是什么。 lsass.exe是Windows系统的一个进程,它主要负责对用户登录信息进行验证和授权。lsass.exe在Windows系统启动时自动运行,并且至关重要。SAM(Security Accounts Manager)注册表是Windows系统中的一个数据库,其中存储着用户名和…

    C# 2023年5月15日
    00
  • ASP.NET中的参数与特殊类型和特性

    ASP.NET中的参数、特殊类型和特性是开发者在开发ASP.NET应用程序时经常需要面对的主题之一。在本篇文章中,我们将向你介绍有关这个主题的完整攻略,包括参数类型、自定义参数绑定、特殊类型对象和在ASP.NET中使用的常见特性。 参数类型 在ASP.NET中,我们可以使用一系列参数类型来接收和指定请求数据。常见的参数类型包括: 基础类型参数:这些参数包括字…

    C# 2023年5月15日
    00
  • C#使用StreamReader读取文件的方法

    下面我将详细讲解C#使用StreamReader读取文件的方法。 简介 StreamReader是.NET Framework中的一个流读取器,它能够从一系列不同类型的流中读取文本。通过使用该类,我们可以轻松地从文件、网络连接等流中读取文本内容。 使用步骤 以下是使用StreamReader读取文件的步骤: 创建StreamReader对象 使用Stream…

    C# 2023年6月1日
    00
  • asp.net获取当前网址url的各种属性(文件名、参数、域名 等)的代码

    当ASP.NET页面和控件运行时,可以通过Request对象的属性来获取当前网址的各种属性。 以下是获取当前网址url的一些常用属性: 获取当前页面的URL Request.Url.AbsoluteUri 该属性返回当前页面的完整URL,包括协议、域名、端口号、路径和查询字符串。如:https://www.example.com/test.aspx?id=1…

    C# 2023年5月31日
    00
  • .Net弹性和瞬态故障处理库Polly实现执行策略

    首先,先简单介绍一下Polly库,Polly是一个.NET弹性和瞬态故障处理库,旨在通过多种执行策略和故障处理机制,帮助我们更好地管理应用程序的异常和故障。以下是实现执行策略的完整攻略: 特殊说明 在本文攻略中,我们将使用Polly库来创建并指定执行策略以处理瞬态故障。在使用Polly时,我们需要先安装Polly库。 步骤一:引用Polly库 首先需要在我们…

    C# 2023年5月15日
    00
  • cryptohack wp day(1)

    就从头开始吧 第一题 (ASCII) 一道简单的ASCII码转换,直接用题目的提示代码解就行了 ascii=[99, 114, 121, 112, 116, 111, 123, 65, 83, 67, 73, 73, 95, 112, 114, 49, 110, 116, 52, 98, 108, 51, 125] flag=”” for i in asci…

    C# 2023年5月4日
    00
  • C#中的自动类型转换和强制类型转换

    C#中的类型转换包括自动类型转换和强制类型转换两种方式。 自动类型转换 当一个变量的数据类型的范围小于另一个变量的数据类型范围时,C#会自动将小范围类型数据转换成大范围类型。这种转换方式叫做自动类型转换。 示例: int a = 10; double b = a; // 自动类型转换 在这个例子中,整型变量a的数据类型范围小于double类型的数据范围。所以…

    C# 2023年5月15日
    00
  • unity scrollRect实现按页码翻页效果

    下面是Unity中ScrollRect实现按页码翻页效果的攻略: 1. 需求分析 首先,我们需要明确我们的需求:利用ScrollRect制作一个翻页效果,实现按页码进行翻页操作。这意味着我们需要按照固定的大小拆分显示内容,每个页面的大小应该相同,并且在翻页时应该有一个平滑的过渡动画。 2. 设置ScrollRect参数 首先,我们需要在Unity中创建一个S…

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