C#线程同步的三类情景分析

C#线程同步的三类情景分析

在多线程的应用中,为了确保数据的正确性,我们需要对线程进行同步,避免多个线程同时对同一份数据进行修改。C#中提供了多种同步机制,其中包括线程同步的三类情景:Mutex、Monitor和AutoResetEvent。

Mutex

Mutex是由操作系统提供的同步原语,可以保证只有一个线程访问临界区。典型的使用方式如下:

using System.Threading;

Mutex mutex = new Mutex();

void Method1()
{
    mutex.WaitOne();
    try 
    {
        // 临界区代码
    }
    finally 
    {
        mutex.ReleaseMutex();
    }
}

void Method2()
{
    mutex.WaitOne();
    try 
    {
        // 临界区代码
    }
    finally 
    {
        mutex.ReleaseMutex();
    }
}

这里使用Mutex来保护两个方法中的临界区,确保它们不会被同时访问。当一个线程获得了Mutex的锁时,其他线程将会阻塞,直到拥有锁的线程释放它。

Monitor

Monitor是.NET Framework提供的同步机制,它可以保证在同一时间内只有一个线程访问临界区。典型的使用方式如下:

using System.Threading;

object lockObject = new object();

void Method1()
{
    lock(lockObject) 
    {
        // 临界区代码
    }
}

void Method2()
{
    lock(lockObject) 
    {
        // 临界区代码
    }
}

这里使用lock关键字来保证两个方法中的临界区不会同时被访问。当一个线程进入临界区时,其他线程将会阻塞,直到当前线程离开临界区。

AutoResetEvent

AutoResetEvent是一个基于事件的同步机制,它允许一个线程等待另一个线程的信号。典型的使用方式如下:

using System.Threading;

AutoResetEvent autoEvent = new AutoResetEvent(false);

void Method1()
{
    // 临界区代码
    autoEvent.Set();
}

void Method2()
{
    autoEvent.WaitOne();
    // 临界区代码
}

这里使用AutoResetEvent来等待Method1的信号,当Method1完成临界区操作后,调用autoEvent.Set()来通知正在等待的线程。Method2调用autoEvent.WaitOne()来等待信号的到来,从而保证临界区操作的同步性。

示例说明

下面是两个示例,演示了如何使用Mutex和Monitor来保护共享资源。

Mutex示例

using System.Threading;

class Counter
{
    private int count = 0;
    private Mutex mutex = new Mutex();

    public void Increment()
    {
        mutex.WaitOne();
        try 
        {
            count++;
        }
        finally 
        {
            mutex.ReleaseMutex();
        }
    }

    public void Decrement()
    {
        mutex.WaitOne();
        try 
        {
            count--;
        }
        finally 
        {
            mutex.ReleaseMutex();
        }
    }

    public int GetCount()
    {
        mutex.WaitOne();
        try 
        {
            return count;
        }
        finally 
        {
            mutex.ReleaseMutex();
        }
    }
}

class Program
{
    static void Main(string[] args)
    {
        Counter c = new Counter();
        Thread t1 = new Thread(() => {
            for(int i = 0; i < 100000; i++) 
            {
                c.Increment();
            }
        });
        Thread t2 = new Thread(() => {
            for(int i = 0; i < 100000; i++) 
            {
                c.Decrement();
            }
        });
        t1.Start();
        t2.Start();
        t1.Join();
        t2.Join();
        Console.WriteLine($"Count: {c.GetCount()}");
    }
}

这个示例演示了如何使用Mutex来保护一个计数器的临界区。Counter类有三个方法:Increment、Decrement和GetCount,这些方法分别执行对计数器的加、减和读操作。每个方法都获取Mutex的锁,并在临界区执行相应的操作。需要注意的是,在GetCount方法中也需要获取Mutex的锁,以保证读操作的安全性。

Monitor示例

using System.Threading;

class BankAccount
{
    private int balance = 0;

    public void Deposit(int amount)
    {
        lock(this) 
        {
            balance += amount;
        }
    }

    public void Withdraw(int amount)
    {
        lock(this) 
        {
            if(balance >= amount)
            {
                balance -= amount;
            }
            else 
            {
                throw new Exception("Insufficient funds");
            }
        }
    }

    public int GetBalance()
    {
        lock(this) 
        {
            return balance;
        }
    }
}

class Program
{
    static void Main(string[] args)
    {
        BankAccount account = new BankAccount();
        Thread t1 = new Thread(() => {
            for(int i = 0; i < 100000; i++) 
            {
                account.Deposit(10);
            }
        });
        Thread t2 = new Thread(() => {
            for(int i = 0; i < 100000; i++) 
            {
                account.Withdraw(10);
            }
        });
        t1.Start();
        t2.Start();
        t1.Join();
        t2.Join();
        Console.WriteLine($"Balance: {account.GetBalance()}");
    }
}

这个示例演示了如何使用Monitor来保护一个银行账户的临界区。BankAccount类有三个方法:Deposit、Withdraw和GetBalance,这些方法分别执行对账户余额的存、取和读操作。使用lock(this)来获取锁,确保每个方法执行时都只有一个线程能够访问临界区。需要注意的是,在Withdraw方法中,如果余额不足,则会抛出异常。同时,GetBalance方法也会获取锁,以保证读操作的安全性。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C#线程同步的三类情景分析 - Python技术站

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

相关文章

  • C#实现毫秒转换成时分秒的方法

    C#实现毫秒转换成时分秒的方法 当我们需要将毫秒转换成可读性更好的时分秒格式时,可以使用C#中提供的方法来进行实现。以下是完整的攻略过程: 1. 使用TimeSpan.FromMilliseconds()方法将毫秒转换成TimeSpan对象 我们可以使用C#中的TimeSpan.FromMilliseconds()方法将毫秒转换成TimeSpan对象,该方法…

    C# 2023年6月1日
    00
  • C# SqlHelper应用开发学习

    C# SqlHelper应用开发学习攻略 1. 学习SqlHelper类 SqlHelper是C#中常用的操作数据库的工具类。学习SqlHelper需要掌握以下几个方面: SqlHelper的基本用法,包括连接数据库、执行SQL语句等; SqlHelper的扩展方法,包括重载的ExecuteNonQuery、ExecuteScalar等; SqlHelper…

    C# 2023年6月2日
    00
  • C#对Json进行序列化和反序列化

    下面我为您详细讲解如何在C#中进行Json的序列化和反序列化。 什么是Json Json(JavaScript Object Notation)是一种轻量级的数据交换格式,具有易于阅读、易于编写的特点。它常被用于将数据从服务器发送到客户端。 Json由两种结构组成:对象和数组。对象是一组无序的键值对,用花括号括起来;数组是一组有序的值,用方括号括起来。基础类…

    C# 2023年5月31日
    00
  • C#使用Aspose.Cells创建和读取Excel文件

    使用Aspose.Cells创建和读取Excel文件可以通过以下步骤实现: 1.下载和安装Aspose.Cells Aspose.Cells可以从官网下载并安装。 2.创建一个新的工作簿并添加工作表 using Aspose.Cells; // 创建一个新的工作簿 Workbook workbook = new Workbook(); // 在工作簿中添加一…

    C# 2023年5月31日
    00
  • C#序列化与反序列化集合对象并进行版本控制

    为了讲解C#序列化与反序列化集合对象并进行版本控制,我们需要先了解以下几个概念: C#序列化 C#序列化是将对象或数据结构转换成可传输的格式,以便可以在网络或磁盘上将数据传输或存储。在C#中,最常用的序列化方式是XML和JSON格式的序列化。 C#反序列化 C#反序列化是将序列化的对象或数据结构转换回原始对象或数据结构的过程。在C#中,最常用的反序列化方式是…

    C# 2023年6月1日
    00
  • c#调用arcgis地图rest服务示例详解(arcgis地图输出)

    在介绍 “C#调用ArcGIS地图REST服务示例详解(ArcGIS地图输出)”这个话题之前,简单介绍一下ArcGIS。 ArcGIS是一款专业的地理信息系统软件,全称“Environmental Systems Research Institute (ESRI) ArcGIS”。ArcGIS提供了从数据收集到最终生产的一整套地理信息系统软件。ArcGIS中…

    C# 2023年5月31日
    00
  • asp.net(c#) RSS功能实现代码

    ASP.NET(C#)中实现RSS功能一般可分为以下步骤: 第一步:准备数据 RSS需要的数据格式一般是XML,所以我们需要准备好相应的XML数据。在ASP.NET中可以使用Linq to XML技术来生成XML,下面是一个示例代码: XElement rss = new XElement("rss", new XAttribute(&q…

    C# 2023年5月31日
    00
  • C# 实现窗口无边框,可拖动效果

    下面我为你详细讲解实现C#窗口无边框、可拖动效果的完整攻略。具体步骤如下: 步骤一:关闭窗口边框 为了实现窗口无边框效果,需要先关闭窗口的边框。在C#中,我们可以通过窗口的FormBorderStyle属性来实现此功能,具体方式如下: this.FormBorderStyle = FormBorderStyle.None; 步骤二:设置窗口背景透明 由于我们…

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