当前位置:首页 > 技术知识 > 正文内容

C# 中的多线程同步机制:lock、Monitor 和 Mutex 用法详解

maynowei2周前 (08-03)技术知识13

在多线程编程中,线程同步是确保多个线程安全地访问共享资源的关键技术。C# 提供了几种常用的同步机制,其中 lock、Monitor 和 Mutex 是最常用的同步工具。本文将全面介绍这三种同步机制的用法、优缺点以及适用场景,帮助开发者在多线程开发中做出合适的选择。

1. lock 关键字 1.1 概述 在 C# 中,lock 关键字是用于线程同步的最常用工具之一。lock 是 Monitor.Enter() 和 Monitor.Exit() 的语法糖,通过锁住一个共享资源来确保在同一时刻只有一个线程可以访问它。lock 适用于同一个进程中的线程同步,尤其是在多个线程访问共享数据时,能够有效地防止数据竞态和线程安全问题。

1.2 用法 lock 关键字的常见用法是围绕一个对象的引用,将其作为锁对象来同步线程。通常,lock 语句会包装一个临界区(共享资源访问区),当一个线程执行完临界区代码后,另一个线程才能进入临界区。 示例代码:

using System;

using System.Threading;

class Program

{

private static readonly object _lock = new object();

// 锁对象

static void Main()

{

Thread t1 = new Thread(DoWork);

Thread t2 = new Thread(DoWork);

t1.Start();

t2.Start();

}

static void DoWork()

{ lock (_lock) // 获取锁 { Console.WriteLine("线程进入临界区...");

Thread.Sleep(1000);

// 模拟处理时间 Console.WriteLine("线程离开临界区...");

}

}

}

说明: 在 lock (_lock) 中,_lock 是锁对象。lock 保证了在同一时刻只有一个线程可以进入 lock 语句块内部的代码。 lock 会在代码块执行完毕后自动释放锁,无需手动释放。 1.3 优缺点 优点: 语法简洁,易于理解和使用。 自动释放锁,减少了因为忘记释放锁而导致死锁的风险。 缺点: 只能用于同一个进程中的线程之间的同步,不能跨进程使用。 无法提供更多的同步控制,比如等待和通知机制。

2. Monitor 类 2.1 概述 Monitor 类是 C# 提供的底层同步机制,比 lock 更加灵活和精细。Monitor 提供了对锁的手动控制,允许你在获取锁后,等待其他线程的通知或条件满足才能继续执行。Monitor 适合那些需要更多同步控制的场景,比如等待和通知机制。 2.2 用法 Monitor 类提供了几个关键的方法: Enter(object obj):尝试获取锁,如果成功,线程继续执行。 Exit(object obj):释放锁,允许其他线程访问锁定的资源。 Wait(object obj):使当前线程等待,直到其他线程通知它。 Pulse(object obj):唤醒一个等待该锁的线程。 PulseAll(object obj):唤醒所有等待该锁的线程。 示例代码:

using System;

using System.Threading;

class Program

{

private static readonly object _lock = new object(); // 锁对象

static void Main()

{

Thread t1 = new Thread(DoWork);

Thread t2 = new Thread(DoWork);

t1.Start();

t2.Start();

}

static void DoWork()

{

Monitor.Enter(_lock);// 获取锁 try

{ Console.WriteLine("线程进入临界区...");

Thread.Sleep(1000);

// 模拟工作

Console.WriteLine("线程离开临界区...");

}

finally { Monitor.Exit(_lock);

// 确保释放锁 } } }

说明:

Monitor.Enter(_lock) 获取锁,Monitor.Exit(_lock) 释放锁。 Monitor 更加底层,提供了细粒度的控制,适用于复杂的同步场景。 使用 try/finally 语句确保即使在发生异常时,也能释放锁。 2.3 优缺点 优点: 比 lock 更灵活,支持等待和通知机制,如 Wait、Pulse 和 PulseAll。 适用于需要更多控制的同步场景。 缺点: 使用起来相对复杂,容易出错,尤其是在手动管理锁时。 只支持同一进程内的线程同步。

相关文章

Win10系统除了移植Objective C,还要有Swift

IT之家讯Build2015大会最让人震惊的莫属微软推出工具,Win10系统可以移植安卓/iOS应用,特别是后者使用的Objective C编程语言,不过最新消息表明,微软连苹果最新的Swift移植也...

Objective-C :Category(category什么意思)

Category 引入在日常的开发中,可能会碰到这样的需求:给某个类增加方法。比如说,需要给NSString类增加一个打印的方法。当然,我们可以新建一个类比如TestString,并继承NSStrin...

Flutter 之 ListView(flutter框架)

在 Flutter 中,ListView 可以沿一个方向(垂直或水平方向)来排列其所有子 Widget,常被用于需要展示一组连续视图元素的场景ListView 构造方法ListView:仅适用于列表中...

ExpandListView 的一种巧妙写法(三十的另一种写法)

ExpandListView大家估计也用的不少了,一般有需要展开的需求的时候,大家不约而同的都想到了它然后以前自己留过记录的一般都会找找以前自己的代码,没有记录习惯的就会百度、谷歌,这里吐槽一下,好几...

Shopee新手指南:Shopee卖家中心用户界面介绍

1.Shopee各站点前台网页链接:2.Shopee各站点后台网页链接3.Shopee APP下载:安卓版下载链接:https://pan.baidu.com/s/1eSp8M1k#list/path...

打通 JAVA 与内核系列之 一 ReentrantLock 锁的实现原理

写JAVA代码的同学都知道,JAVA里的锁有两大类,一类是synchronized锁,一类是concurrent包里的锁(JUC锁)。其中synchronized锁是JAVA语言层面提供的能力,在此不...