1、Monitor.Enter(obj);申请对obj(非静态字段)的独立访问权;
2、对静态字段加锁时,使用Monitor.Enter(typeof(共享类名));
示例:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
namespace Thread_Monitor
{
class ShearedResource //多线程共享的资源
{
public int instanceCount = 0; //!实例字段
public static int counter = 0; //!静态字段
}
class Program
{
private static void IncreaseCount(Object obj)
{
Monitor.Enter(obj);
int beginNum = (obj as ShearedResource).instanceCount;
for (int i = 0; i < 100000; i++)
beginNum++;
(obj as ShearedResource).instanceCount = beginNum;
Console.WriteLine("Thread ID:{0}, Count: {1}", Thread.CurrentThread.ManagedThreadId, beginNum);
Monitor.Exit(obj);
}
private static void IncreaseStaticCount()
{
Monitor.Enter(typeof(ShearedResource));
int beginNum = ShearedResource.counter;
for (int i = 0; i < 100000; i++)
beginNum++;
ShearedResource.counter = beginNum;
Console.WriteLine("Thread ID:{0}, Count: {1}", Thread.CurrentThread.ManagedThreadId, beginNum);
Monitor.Exit(typeof(ShearedResource));
}
static void Main(string[] args)
{
const int threadCount = 15;
ShearedResource sr = new ShearedResource();
Thread[] threads = new Thread[threadCount];
for (int i = 0; i < threadCount; i++)
{
threads[i] = new Thread(new ParameterizedThreadStart(IncreaseCount)).Start(sr); //!线程带参
//threads[i] = new Thread(IncreaseStaticCount).Start();
}
Console.ReadKey();
}
}
}
访问静态字段
private static void IncreaseCount(Object obj)
{
Monitor.Enter(typeof(ShearedResource));
int beginNum = ShearedResource.counter;
for (int i = 0; i < 100000; i++)
beginNum++;
ShearedResource.counter = beginNum;
Console.WriteLine("Thread ID:{0}, Count: {1}", Thread.CurrentThread.ManagedThreadId, beginNum);
Monitor.Exit(typeof(ShearedResource));
}
3、使用Monitor控制线程的推进顺序
(1)B执行Monitor.Wait(obj)后阻塞,等待A执行Monitor.Pulse(obj)。一旦A执行Monitor.Pulse(obj),将通知B让其继续走下去。
(2)必须确保线程B先执行,否则会产出死锁,线程B将永远等不到A的消息。
(3)每调用一次Monito.Pulse()方法,等待队列里的一个线程被激活;调用Monitor.PulseAll()方法,激活等待队列里的所有线程。
//线程A的执行代码
lock(obj)
{
//访问共享资源obj...
Monitor.Pulse(obj);
}
//线程B的执行代码
lock(obj)
{
Monitor.Wait(obj);
//访问共享资源obj...
}
4、用Attribute实现
[MethodImpl(MethodImplOptions.Synchronized)]
private static void IncreaseCount(Object obj)
{
//访问共享资源...
}
好处,不需要改内部代码。
需引入命名空间:using System.Runtime.CompilerServices;
此方法是锁定类中一个方法,不是锁定整个类
5、指定超时选项以避免死锁
基本用法:
bool lockTaken = false;
Monitor.TryEnter(lockObj, 3000, ref lockTaken); //超时3秒, lockTaken为引用类型
if(lockTaken)
{
try
{ //访问共享资源.... }
finally
{
Monitor.Exit(lockObj);
}
}