C#中lock,Monitor,Mutex多线程同步应用实例比较
C#中可以使用Monitor类、lock和Mutex类来进行多线程的同步。具体的应用实例比较代码如下:
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
namespace ConsoleApplication2
{
class Program
{
#region variable
Thread thread1 = null;
Thread thread2 = null;
Mutex mutex = null;
private static Object sto = new Object();//私有静态锁定对象
#endregion
static void Main(string[] args)
{
Program p = new Program();
p.RunThread();
Console.ReadLine();
}
public Program()
{
mutex = new Mutex();
//演示无同步的情况
//thread1 = new Thread(new ThreadStart(thread1Func));
//thread2 = new Thread(new ThreadStart(thread2Func));
//演示使用lock同步线程3和4,并使线程3和4按照调用顺序来依次执行
thread1 = new Thread(new ThreadStart(thread3Func));
thread2 = new Thread(new ThreadStart(thread4Func));
//演示使用Monitor同步线程5和6,并使线程5和6按照调用顺序来依次执行
//thread1 = new Thread(new ThreadStart(thread5Func));
//thread2 = new Thread(new ThreadStart(thread6Func));
//演示使用Mutex同步线程7和8,但不能同步线程7或8中for循环的执行
//thread1 = new Thread(new ThreadStart(thread7Func));
//thread2 = new Thread(new ThreadStart(thread8Func));
//演示使用lock同步线程33和44,并先执行完线程33后,再执行线程44
//thread1 = new Thread(new ThreadStart(thread33Func));
//thread2 = new Thread(new ThreadStart(thread44Func));
//演示使用Monitor同步线程55和66,并先执行完线程55后,再执行线程66
//thread1 = new Thread(new ThreadStart(thread55Func));
//thread2 = new Thread(new ThreadStart(thread66Func));
//演示使用Mutex同步线程77和88,并先执行完线程77后,再执行线程88
//thread1 = new Thread(new ThreadStart(thread77Func));
//thread2 = new Thread(new ThreadStart(thread88Func));
}
public void RunThread()
{
thread1.Start();
thread2.Start();
}
private void TestFunc(string str)
{
Console.WriteLine("{0} {1}", str, System.DateTime.Now.ToLongTimeString() + ":" + System.DateTime.Now.Millisecond.ToString());
Thread.Sleep(50);
}
//无同步的情况
private void thread1Func()
{
for (int count = 0; count < 10; count++)
{
TestFunc("Thread1 have run " + count.ToString() + " times");
Thread.Sleep(50);
}
}
private void thread2Func()
{
for (int count = 0; count < 10; count++)
{
TestFunc("Thread2 have run " + count.ToString() + " times");
Thread.Sleep(100);
}
}
//使用lock同步线程3和4,并使线程3和4按照调用顺序来依次执行
private void thread3Func()
{
for (int count = 0; count < 10; count++)
{
lock (sto)
{
TestFunc("Thread3 have run " + count.ToString() + " times");
Thread.Sleep(50);
}
}
}
private void thread4Func()
{
for (int count = 0; count < 10; count++)
{
lock (sto)
{
TestFunc("Thread4 have run " + count.ToString() + " times");
Thread.Sleep(100);
}
}
}
//使用lock同步线程33和44,并先执行完线程33后,再执行线程44
private void thread33Func()
{
lock (sto)
{
for (int count = 0; count < 10; count++)
{
TestFunc("Thread33 have run " + count.ToString() + " times");
Thread.Sleep(50);
}
}
}
private void thread44Func()
{
lock (sto)
{
for (int count = 0; count < 10; count++)
{
TestFunc("Thread44 have run " + count.ToString() + " times");
Thread.Sleep(100);
}
}
}
//使用Mutex同步线程7和8,但不能同步线程7或8中for循环的执行
private void thread7Func()
{
for (int count = 0; count < 10; count++)
{
mutex.WaitOne();
TestFunc("Thread7 have run " + count.ToString() + " times");
Thread.Sleep(50);
mutex.ReleaseMutex();
}
}
private void thread8Func()
{
for (int count = 0; count < 10; count++)
{
mutex.WaitOne();
TestFunc("Thread8 have run " + count.ToString() + " times");
Thread.Sleep(100);
mutex.ReleaseMutex();
}
}
//使用Mutex同步线程77和88,并先执行完线程77后,再执行线程88
private void thread77Func()
{
mutex.WaitOne();
for (int count = 0; count < 10; count++)
{
TestFunc("Thread77 have run " + count.ToString() + " times");
Thread.Sleep(50);
}
mutex.ReleaseMutex();
}
private void thread88Func()
{
mutex.WaitOne();
for (int count = 0; count < 10; count++)
{
TestFunc("Thread88 have run " + count.ToString() + " times");
Thread.Sleep(100);
}
mutex.ReleaseMutex();
}
//使用Monitor同步线程5和6,并使线程5和6按照for循环的调用顺序来依次执行
//Monitor和Lock可以互斥本线程的重复调用
private void thread5Func()
{
for (int count = 0; count < 10; count++)
{
Monitor.Enter(sto);
TestFunc("Thread5 have run " + count.ToString() + " times");
Thread.Sleep(50);
Monitor.Exit(sto);
}
}
private void thread6Func()
{
for (int count = 0; count < 10; count++)
{
Monitor.Enter(sto);
TestFunc("Thread6 have run " + count.ToString() + " times");
Thread.Sleep(100);
Monitor.Exit(sto);
}
}
//使用Monitor同步线程55和66,并先执行完线程55后,再执行线程66
private void thread55Func()
{
Monitor.Enter(sto);
for (int count = 0; count < 10; count++)
{
TestFunc("Thread55 have run " + count.ToString() + " times");
Thread.Sleep(50);
}
Monitor.Exit(sto);
}
private void thread66Func()
{
Monitor.Enter(sto);
for (int count = 0; count < 10; count++)
{
TestFunc("Thread66 have run " + count.ToString() + " times");
Thread.Sleep(100);
}
Monitor.Exit(sto);
}
}
}
具体输出分析如下:
1.无同步的输出效果:
2个线程同时开始执行;2个线程从第1次往后,thread1的执行间隔约是100,thread2的执行间隔约是150;
2.lock同步的输出效果:
使用lock同步线程3和4,并使线程3和4按照for循环调用顺序来依次执行。
3.Monitor同步的输出效果:
使用Monitor同步线程5和6,并使线程5和6按照for循环调用顺序来依次执行。
4. Mutex同步的输出效果:
Mutex同步线程7和8,但不能同步线程7或8中for循环的执行顺序。
5. Mutex同步线程33和44的输出效果:
使用lock同步线程33和44,并先执行完线程33后,再执行线程44。
6. Mutex同步线程55和66的输出效果:
使用Monitor同步线程55和66,并先执行完线程55后,再执行线程66。
7. Mutex同步线程77和88的输出效果:
使用Mutex同步线程77和88,并先执行完线程77后,再执行线程88。
应用实例比较结果:
(1)Mutex只能互斥不同线程间的调用,但是不能互斥本线程的重复调用。
(2)monitor和lock不但能互斥本线程(防止本线程重入),也能互斥其他线程的重复调用。(注意锁定对象的设定)