Skip to content

使用互斥体(Mutex)实现同步

🏷️ C# 学习

互斥体是操作系统内同步线程的内核对象,有相应的 Win32 函数来操作互斥体对象。

在.NET 中,Mutex类封装了所有互斥体的操作。

Mutex类型和Monitor类型(lock)的区别:

  1. 使用Mutex的效率非常低,相对于Monitor类型等线程同步机制来说,操作系统互斥体的效率要慢 10 倍以上。

  2. 操作系统的互斥体对系统上的所有进程都有效,也就是说它是跨进程的。

点击查看代码
cs
using System;
using System.Diagnostics;
using System.IO;
using System.Text;
using System.Threading;

namespace UseMutex
{
    /// <summary>
    /// 这里测试 Mutex 的作用,程序本身是单线程的
    /// 但最终测试时将多个进程同时执行
    /// </summary>
    class Program
    {
        const string _testFile = "D:\\testMutex.txt";
        /// <summary>
        /// 这个互斥体可以保证所有进程得到同步
        /// </summary>
        static Mutex mutex = new Mutex(false, "TestMutex");

        /// <summary>
        /// 测试互斥体
        /// </summary>
        /// <param name="args"></param>
        static void Main(string args)
        {
            // 留出时间来启动其它进程
            Thread.Sleep(3 * 1000);
            DoWork();
            mutex.Close();
            Console.Read();
        }

        /// <summary>
        /// 往文件里写连续的内容
        /// </summary>
        static void DoWork()
        {
            long d1 = DateTime.Now.Ticks;
            // 进入互斥
            mutex.WaitOne();
            long d2 = DateTime.Now.Ticks;
            Console.WriteLine("经过{0}个 Tick 进程后{1}得到互斥体,进入临界区代码。",
                (d2-d1).ToString(),
                Process.GetCurrentProcess().Id.ToString());
            try
            {
                if (!File.Exists(_testFile))
                {
                    using (FileStream fs = File.Create(_testFile))
                    { }
                }
                for (int i = 0; i < 5; i++)
                {
                    using (FileStream fs = File.Open(_testFile, FileMode.Append))
                    {
                        string content = "【进程" + Process.GetCurrentProcess().Id.ToString() + "】:" + i.ToString() + "\r\n";
                        byte data = Encoding.Default.GetBytes(content);
                        fs.Write(data, 0, data.Length);
                        Thread.Sleep(300);
                    }
                }
            }
            catch (Exception)
            {

                throw;
            }
            finally
            {
                // 退出互斥
                mutex.ReleaseMutex();
            }

        }
    }
}

同时执行 3 个进程时的输出结果:

点击查看输出结果
【进程2336】:0
【进程2336】:1
【进程2336】:2
【进程2336】:3
【进程2336】:4
【进程7256】:0
【进程7256】:1
【进程7256】:2
【进程7256】:3
【进程7256】:4
【进程11716】:0
【进程11716】:1
【进程11716】:2
【进程11716】:3
【进程11716】:4