惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

T
Threatpost
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
S
Security Affairs
N
News and Events Feed by Topic
T
Tenable Blog
P
Proofpoint News Feed
W
WeLiveSecurity
Simon Willison's Weblog
Simon Willison's Weblog
Google DeepMind News
Google DeepMind News
C
CERT Recently Published Vulnerability Notes
Help Net Security
Help Net Security
I
Intezer
T
Threat Research - Cisco Blogs
S
Secure Thoughts
C
Cyber Attacks, Cyber Crime and Cyber Security
L
Lohrmann on Cybersecurity
AWS News Blog
AWS News Blog
Google Online Security Blog
Google Online Security Blog
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
Know Your Adversary
Know Your Adversary
Project Zero
Project Zero
The Hacker News
The Hacker News
Security Archives - TechRepublic
Security Archives - TechRepublic
T
Tor Project blog
N
News | PayPal Newsroom
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
Hacker News - Newest:
Hacker News - Newest: "LLM"
A
Arctic Wolf
Forbes - Security
Forbes - Security
O
OpenAI News
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
Security Latest
Security Latest
P
Palo Alto Networks Blog
S
Schneier on Security
S
Securelist
C
Cybersecurity and Infrastructure Security Agency CISA
H
Heimdal Security Blog
V
Vulnerabilities – Threatpost
www.infosecurity-magazine.com
www.infosecurity-magazine.com
博客园_首页
T
Troy Hunt's Blog
Latest news
Latest news
Recent Announcements
Recent Announcements
MyScale Blog
MyScale Blog
人人都是产品经理
人人都是产品经理
L
LINUX DO - 热门话题
M
MIT News - Artificial intelligence
N
Netflix TechBlog - Medium
V
Visual Studio Blog
H
Hacker News: Front Page

博客园 - 邢帅杰

.net core使用SharpZipLib压缩zip文件并设置密码 CSRedisCore用法 Android 常用数据目录(内部 / 外部、缓存、文件) 的 获取方法对照表 安卓把assets中的文件copy到app目录中 oracle执行sql语句前清除缓存 安卓开发使用interface自定义回调函数 安装DockerDesktop并启用 oracle中decode用法 vue使用import.meta编译报错,import.meta.env报:类型“ImportMeta”上不存在属性“env”。必须配置module。 oracle游标使用详解 oracle存储过程中声明一个行变量,接收游标中的行数据。variable_name table_name%ROWTYPE oracle NVL和NVL2 C#获取文件md5码 oracle查询存储过程和函数中是否包含某个字符串 Android清除WebView缓存 C#获取当前日期是星期几 切换项目git地址,项目迁移到新git地址 Android Stack说明 安卓打开第三方app并传入参数 安卓如何唤醒深度睡眠的设备并执行任务 java两个日期相差秒数
C#线程同步、跨进程同步Mutex详解、C#只允许运行一个实例
邢帅杰 · 2025-06-19 · via 博客园 - 邢帅杰

Mutex 是 .NET 中用于线程同步和进程同步的一种工具。它的主要作用是确保在某一时刻只有一个线程或进程可以访问某个共享资源。下面是关于 Mutex 的详细介绍:
1. Mutex 的基本概念
Mutex(互斥锁)是一种同步原语,用于在多线程或多进程环境中,确保同一时间只有一个线程或进程访问特定的代码段或共享资源。它的主要目的是避免竞争条件,防止多个线程或进程同时操作共享资源,导致数据不一致或程序崩溃。
2. Mutex 的用途
线程同步:在单个进程内,当多个线程尝试访问共享资源时,可以使用 Mutex 来同步这些线程,避免数据冲突。
进程同步:不同进程中的线程如果要共享资源,也可以使用 Mutex 来确保同一时间只有一个进程在访问该资源。
3. 创建和获取 Mutex
创建和获取一个 Mutex 的常见方式:
Mutex mutex = new Mutex(); // 创建一个未被拥有的互斥锁
使用命名 Mutex(跨进程同步):
Mutex mutex = new Mutex(true, "MyMutexName", out bool acquired);
true:表示程序在创建时就尝试获取锁(初始所有者)。
"MyMutexName":这是互斥锁的名称。这个名称是唯一的,跨进程共享。如果其他进程使用相同的名称,就表示它们在访问相同的互斥锁。
out bool acquired:这个 out 参数表示当前进程是否成功获取到了互斥锁。acquired 为 true 表示成功获得锁,false 表示无法获得锁。
获取锁:mutex.WaitOne(); // 获取锁,直到成功
WaitOne:这个方法会使当前线程等待,直到它能够成功获取到互斥锁。如果锁已经被其他线程或进程持有,当前线程将阻塞,直到锁被释放。
释放锁:mutex.ReleaseMutex(); // 释放锁
ReleaseMutex():当一个线程或者进程完成对共享资源的操作后,需要调用 ReleaseMutex 来释放锁。这样,其他线程或进程就可以获取该锁,继续访问共享资源。
4. Mutex 的工作原理
同一进程中的线程:
独占性:一个 Mutex 对象在同一时刻只能被一个线程持有。如果一个线程已经持有了互斥锁,其他线程必须等待,直到持有锁的线程释放它。
跨进程的互斥:
跨进程共享:当 Mutex 使用名称时,多个进程可以通过相同的名称来访问同一个互斥锁。这允许跨进程的同步,确保不同进程不会同时访问同一个共享资源。
5. 常见方法和属性
Mutex.WaitOne():用来请求并获取互斥锁。如果锁已经被占用,当前线程会被阻塞,直到锁可用。
Mutex.ReleaseMutex():用来释放锁。只有持有锁的线程才可以调用此方法释放锁,其他线程不能调用。
Mutex.WaitOne(int millisecondsTimeout):尝试获取锁,如果锁在指定的时间内没有被占用,它就会成功获取锁。如果时间过期,返回 false。
Mutex.WaitOne(TimeSpan timeout):类似于上面的 millisecondsTimeout,但是使用 TimeSpan 来指定等待的时间。
Mutex.WaitOne(TimeSpan timeout, bool exitContext):除了指定超时时间外,还可以指定退出上下文(例如是否释放其他同步资源)。
Mutex.Dispose():销毁 Mutex 对象并释放它占用的资源。在不再需要 Mutex 时应调用此方法。
6. Mutex 与 Monitor 的区别
Mutex 和 Monitor 都可以用于同步线程,但它们有一些显著的区别:
Mutex可以用于线程同步,也可以用于进程同步;相对较慢,因为它支持进程间同步;不支持继承;当你需要跨进程同步时使用 Mutex。
Monitor仅用于线程同步;性能较高,只用于同一进程中的线程同步;支持继承;当你只需要线程间同步时使用 Monitor。
Mutex 是一种跨进程的同步机制,可以在不同进程之间进行同步。
Monitor 主要用于同一个进程中的线程同步,不支持跨进程同步。
7. 示例:互斥锁确保程序只有一个实例
假设我们希望确保某个程序只能有一个实例运行,可以使用命名的 Mutex 来实现:
class Program
{
  static Mutex mutex = new Mutex(true, "MyUniqueMutexName", out bool createdNew);
  static void Main()
  {
    if (!createdNew)
    {
      Console.WriteLine("The application is already running.");
      return;
    }
    Console.WriteLine("Application is running. Press any key to exit...");
    Console.ReadKey();
    mutex.ReleaseMutex();
  }
}
//方式2
//这里使用了Mutex的另一种构造方式,它会返回一个布尔值,指示是否成功创建了互斥体(即是否当前是第一个实例)。
//如果不是第一个实例,则显示消息并退出。注意这里的Global\\前缀是为了使互斥体在所有会话中都是全局的。
bool createdNew;
var mutex = new Mutex(true, "Global\\" + Application.ProductName, out createdNew);
if (!createdNew)
{
  MessageBox.Show("应用程序已经在运行!");
  return; // 退出程序
}
8. 注意事项
释放互斥锁:每次成功获取锁后,都必须确保释放锁,否则其他线程或进程将无法访问该资源,可能导致死锁。
死锁:如果两个线程持有相互依赖的锁并且都在等待对方释放锁,就会发生死锁。为了避免死锁,要谨慎设计锁的获取顺序。
跨进程使用:只有在互斥锁使用名称时,它才可以跨进程同步。普通的 Mutex 仅限于单个进程内部。
9. 总结
Mutex 是一种跨线程、跨进程的同步机制,确保同一时刻只有一个线程或进程访问共享资源。
它具有独占性,一个线程/进程在持有锁时,其他线程/进程无法访问该资源。
在多进程同步时,使用命名的 Mutex 对象,通过共享的名字来实现不同进程间的同步。
在使用 Mutex 时,要确保在使用完资源后正确释放锁,以避免死锁和资源浪费。
原文链接:https://blog.csdn.net/skvjw/article/details/144258403

posted on 2025-06-19 11:20  邢帅杰  阅读(358)  评论()    收藏  举报