勇哥注:
《多线程安全》这个系列会持续写下去,它是我的一个弱点,有兴趣的朋友可以选择性看看。
const string mutexName = "勇哥";
public static Mutex mutexObj = new Mutex(false, mutexName); 定义了一个全局锁,false表示创建互斥锁之后持有状态是:没有人持有
命名“勇哥”,将做为全局的操作系统互斥量,请务必正确关闭互斥量,否则关掉这个进程后再也进不去。
这种特性使得互斥量经常被用作“不允许进程同时运行两个副本”。
下面的源码的目的是:
并发执行a.show()和b.show(),但是两者应该依次执行, a.show()完成后再b.show(),或者反过来。
源码:
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; using System.Windows.Forms; namespace WindowsFormsApp1 { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { classA a = new classA(); classB b = new classB(); Task.Run(() => { if (Program.mutexObj.WaitOne()) { a.show(); Program.mutexObj.ReleaseMutex(); } }); Task.Run(() => { if (Program.mutexObj.WaitOne()) { b.show(); Program.mutexObj.ReleaseMutex(); } }); } } public class classA { public void show() { for (int i = 0; i < 5; i++) { int k = i; var res=Task.Run(() => { Console.WriteLine($"{i},{k},classAstart...[{Thread.CurrentThread.ManagedThreadId}]"); Thread.Sleep(1000); Console.WriteLine($"{i},{k},classAend...[{Thread.CurrentThread.ManagedThreadId}]"); }); res.Wait(); } } } public class classB { public void show() { for (int i = 0; i < 5; i++) { int k = i; var res=Task.Run(() => { Console.WriteLine($"{i},{k},classBstart...[{Thread.CurrentThread.ManagedThreadId}]"); Thread.Sleep(1000); Console.WriteLine($"{i},{k},classBend...[{Thread.CurrentThread.ManagedThreadId}]"); }); res.Wait(); } } } }
锁在Program.cs中定义
static class Program { const string mutexName = "勇哥"; public static Mutex mutexObj = new Mutex(false, mutexName); /// <summary> /// 应用程序的主入口点。 /// </summary> [STAThread] static void Main() { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new Form1()); } }
网上有另一个例子,也很好,勇哥转载如下:
C# 中 Mutex 类也是用于线程同步操作的类,例如,当多个线程同时访问一个资源时保证一次只能有一个线程访问资源。 在 Mutex 类中,WaitOne() 方法用于等待资源被释放, ReleaseMutex() 方法用于释放资源。 WaitOne() 方法在等待 ReleaseMutex() 方法执行后才会结束。 【实例】使用线程互斥实现每个车位每次只能停一辆车的功能。 根据题目要求,停车位即为共享资源,实现的代码如下。
class Program { private static Mutex mutex = new Mutex(); public static void PakingSpace(object num) { if (mutex.WaitOne()) { try { Console.WriteLine("车牌号{0}的车驶入!", num); Thread.Sleep(1000); } finally { Console.WriteLine("车牌号{0}的车离开!", num); mutex.ReleaseMutex(); } } } static void Main(string[] args) { ParameterizedThreadStart ts = new ParameterizedThreadStart(PakingSpace); Thread t1 = new Thread(ts); t1.Start("冀A12345"); Thread t2 = new Thread(ts); t2.Start("京A00000"); } }
从上面的运行效果可以看出,每辆车驶入并离开后其他车才能占用停车位,即当一个线程占用资源时,其他线程是不使用该资源的。
再来一个例子,也是让并发执行变成交替执行。
这个是同时使用lock+mutex,如果你多次执行,会出现例外的情况,勇哥解释不了也没时间研究,有兴趣的童鞋可以看看。
源码如下:
using System; using System.Collections.Generic; using System.Text; using System.Threading; namespace MonitorLockMutex { class Program { #region variable Thread thread1 = null; Thread thread2 = null; Mutex mutex = null; #endregion static void Main(string[] args) { Program p = new Program(); p.RunThread(); Console.ReadLine(); } public Program() { mutex = new Mutex(); thread1 = new Thread(new ThreadStart(thread1Func2)); thread2 = new Thread(new ThreadStart(thread2Func2)); } public void RunThread() { thread1.Start(); thread2.Start(); } private void thread1Func() { for (int count = 0; count < 10; count++) { TestFunc2("Thread1 have run " + count.ToString() + " times"); Thread.Sleep(30); } } private void thread2Func() { for (int count = 0; count < 10; count++) { TestFunc2("Thread2 have run " + count.ToString() + " times"); Thread.Sleep(100); } } private void TestFunc(string str) { Console.WriteLine("{0} {1}", str, System.DateTime.Now.Millisecond.ToString()); Thread.Sleep(50); } private void TestFunc2(string str) { lock (this) { Console.WriteLine("{0} {1}", str, System.DateTime.Now.Millisecond.ToString()); Thread.Sleep(50); } } private void thread1Func2() { for (int count = 0; count < 10; count++) { lock (this) { mutex.WaitOne(); TestFunc("Thread1 have run " + count.ToString() + " times"); mutex.ReleaseMutex(); } } } private void thread2Func2() { for (int count = 0; count < 10; count++) { lock (this) { mutex.WaitOne(); TestFunc("Thread2 have run " + count.ToString() + " times"); mutex.ReleaseMutex(); } } } } }
---------------------
作者:hackpig
来源:www.skcircle.com
版权声明:本文为博主原创文章,转载请附上博文链接!

