.net各种锁和通知

1.锁的种类和用途
a. 简单锁 b.互锁 c.读写锁
多个线程同时访问同一项资源,可能导致死锁和饥饿等问题。
2. 简单锁(互斥锁)
锁最简单的方式是使用lock语句,最适合保护不超过一个方法的小型代码块。
不同锁定公有类型(lock(typeof(PublicType))或类型实例(lock(this))

private int counter;
private static readonly object synclock = new object();
public int Increment()
{
lock(synclock)
{
	return this.counter++
}
}

public int Decrement()
{
	lock(synclock)
		{
			return this.counter++;
		}
}

3. Interlocked 原子锁 轻量级
interlocked系列方法提供了对简单类型的原子操作(不会被打断的操作)。
什么说它是轻量级呢?因为它仅对整形数据(即int类型,long也行)进行同步。如果你学过操作系统里面的PV操作(即信号量),那么你对它已经了解了一般。它实现的正是如同信号量的功能。
Interlocked.Increment(ref value)
数值加一(原子性操作)
Interlocked.Decrement(ref value)
数值减一(原子性操作)
Interlocked.Exchange(ref value1, value2)
交换:把值2赋给值1;返回新值
Interlocked.CompareExchange(ref value1, value2, value3)
实现比较和交换两种功能:值1和值3比较,如果相同,把值2给值1,不相同则不作任何操作;返回原值(多用于判断条件)

3.1 以原子方式递增
int i = 0 ;
Interlocked.Increment( ref i);
3.2 单例模式中的双检测技术

internal sealed class MySingleton
{
	private static MySingleton s_value = null;
	public static MySingleton GetMySingleton()
	{
		if(s_value != null) return s_value;
		MySingleton temp = new MySingleton();
		Interlocked.CompareExchange(ref s_value, temp. null);
		return s_value;
	}
}
  1. ReadWriterLock 读写锁
    加粗样式(1)有时对于共享资源应当区分读和写,因为读的时候往往是允许多线程同时读的,因为这不会造成混乱;而只有在需要写的时候才不允许其他线程读或者写。
    (2).NET的ReaderWriterLock和ReaderWriterLockSlim为我们提供了区分读和写的锁。这种方式在有些情况下通常比Monitor更高效。
    (3)在MSDN中推荐使用的是ReaderWriterLockSlim类,其解释是ReaderWriterLockSlim用一种简单的规则处理递归调用以及更好的支持锁升级机制,而且能更好的避免死锁的发生,最后它比ReaderWriterLock更高效。

4.1 读写锁的三种模式
Read Mode 读模式:表示线程试图对共享资源进行读操作,而不会写。ReaderWriterLockSlim.EnterReadLock
ReaderWriterLockSlim.TryEnterReadLock
WriteMode 写模式:表示线程对共享资源进行写操作。
ReaderWriterLockSlim.EnterWriteLock
ReaderWriterLockSlim.TryEnterWriteLock
Upgradeable Read Mode:读模式,但可能将来升级成写锁。ReaderWriterLockSlim.EnterUpgradeableReadLock
ReaderWriterLockSlim.TryEnterUpgradeableReadLock
读锁升级
同一时刻只能有一个线程获得可升级读锁,当获得可升级读锁的线程试图获得写锁的时候或可以调用EnterWriteLock,如果此时有线程没有释放写锁的话,EnterWriteLock会阻塞直到所有的读锁释放,同时试图获得读锁的线程也将阻塞(这里不用考虑写锁,因为既然可以获得可升级读锁,那么必然不存在写锁),这有点像“关门放狗”,关上门不让狗进来,而把已经在里面的狗放走)
4.2 例子
读/写模式

    private ReaderWriterLockSlim cacheLock = new ReaderWriterLockSlim();
    private Dictionary<int, string> innerCache = new Dictionary<int, string>();

    public int Count
    { get { return innerCache.Count; } }

    public string Read(int key)
    {
        cacheLock.EnterReadLock();
        try
        {
            return innerCache[key];
        }
        finally
        {
            cacheLock.ExitReadLock();
        }
    }
    public void Delete(int key)
    {
        cacheLock.EnterWriteLock();
        try
        {
            innerCache.Remove(key);
        }
        finally
        {
            cacheLock.ExitWriteLock();
        }
    }

5.使用通知
使用手动重置通知ManualResetEvent/ManualResetEventSlim 类实现
通知一个或多个正在等待的线程已发生事件
5.1 例子

private ManualResetEvent _mre = new ManualResetEvent(true);
public void AddMsg(BusMsg msg)
{
	if(msg == null) return;
	lock(_lockObj)
	{
		_taskQueue.Enqueue(msg);
		_mre.Set(); //释放线程
	}
}
public void Run()
{
	BusMsg msg = null;
	while(true)
	{
		_mre.WaiteOne();//等待,阻止当前线程,直到当前 WaitHandle 收到信号。
		if(_taskQueue.Count == 0)
		{
			 _mre.Reset();	//重启线程
			 continnue;
		}
		msg = GetMsg();
		if(msg!=null)
			DoBusMsg(msg);
		else
			_mre.Reset();

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值