看完上面的代码,让我增加了两点认识:
1、Thread.BeginCriticalRegion()和Thread.EndCriticalRegion();
因为这段时间正好看了一本多线程编程的书,既然将上面方法认为是进入临界区和退出临界区,对于临界区而言,进入该区的数据,在没有退出之前,如果临界区外的程序需要使用它,那么就必须出于等待。所以觉得已经使用临界区,为什么还要使用Semaphore?!
可是,MS只是取了个相同的名字,做的事情完全不同,上面两个方法完全没有临界区的概念,它只是设置一个区域(Begin到End之间),表示该区域内发生线程中断或未处理的异常会影响整个应用程序域。
2、m_Waiters的作用
一开始以为在Enter的时候,直接写上:m_WaiterLock.WaitOne();Exit的时候,写上:m_WaiterLock.Release(1);这样就可以了。m_Waiters有什么意义?!
优化性能,Semaphore是内核对象,我们都知道,要尽量少的进入内核模式,因为这是很消耗性能,所以尽量少的使用内核对象。m_Waiters的意义就在这里,如果只有一个线程使用该锁对象的时候,是不需要去获取和释放的。 OK,上述的东西都是铺垫,铺完了也就进入主题了!
多线程的思维
优化的Optex
namespace ThreadConcurrent.Lock
{
public sealed class Optex : IDisposable
{
/// <summary>
/// 琐的状态
/// </summary>
private Int32 m_LockState = c_lsFree;
/// <summary>
/// 自由状态
/// </summary>
private const Int32 c_lsFree = 0x00000000;
/// <summary>
/// 被拥有状态
/// </summary>
private const Int32 c_lsOwned = 0x00000001;
/// <summary>
/// 等待的线程数
/// </summary>
private const Int32 c_1Waiter = 0x00000002;
private Semaphore m_WaiterLock = new Semaphore(0, Int32.MaxValue);
#region 构造函数
/// <summary>
///
/// </summary>
public Optex() { }
#endregion
/// <summary>
/// 请求锁
/// </summary>
public void Enter()
{
Thread.BeginCriticalRegion();
while (true)
{
Int32 ls = InterlockedOr(ref m_LockState, c_lsOwned);
//自由状态
if ((ls & c_lsOwned) == c_lsFree) return;
// 增加等待的线程数
if (IfThen(ref m_LockState, ls, ls + c_1Waiter))
{
m_WaiterLock.WaitOne();
}
}
}
public void Exit()
{
// 释放琐
Int32 ls = InterlockedAnd(ref m_LockState, ~c_lsOwned);
//无等待的线程
if (ls == c_lsOwned)
{
}
else
{
ls &= ~c_lsOwned;
if (IfThen(ref m_LockState, ls & ~c_lsOwned, ls - c_1Waiter))
{
m_WaiterLock.Release(1);
}
else
{
}
}
Thread.EndCriticalRegion();
}
#region 原子化操作
/// <summary>
/// 与操作
/// </summary>
/// <param name="target"></param>
/// <param name="with"></param>
/// <returns></returns>
private static Int32 InterlockedAnd(ref Int32 target, Int32 with)
{
Int32 i, j = target;
do
{
i = j;
j = Interlocked.CompareExchange(ref target, i & with, i);
} while (i != j);
return j;
}
/// <summary>
/// 或操作
/// </summary>
/// <param name="target"></param>
/// <param name="with"></param>
/// <returns></returns>
private static Int32 InterlockedOr(ref Int32 target, Int32 with)
{
Int32 i, j = target;
do
{
i = j;
j = Interlocked.CompareExchange(ref target, i | with, i);
} while (i != j);
return j;
}
#endregion
private static Boolean IfThen(ref Int32 val, Int32 @if, Int32 then)
{
return (Interlocked.CompareExchange(ref val, @then, @if) == @if);
}
private static Boolean IfThen(ref Int32 val, Int32 @if, Int32 then, out Int32 prevVal)
{
prevVal = Interlocked.CompareExchange(ref val, @then, @if);
return (prevVal == @if);
}
/// <summary>
/// 释放资源
/// </summary>
public void Dispose()
{
if (m_WaiterLock != null)
{
m_WaiterLock.Close();
m_WaiterLock = null;
}
}
}
}
{
public sealed class Optex : IDisposable
{
/// <summary>
/// 琐的状态
/// </summary>
private Int32 m_LockState = c_lsFree;
/// <summary>
/// 自由状态
/// </summary>
private const Int32 c_lsFree = 0x00000000;
/// <summary>
/// 被拥有状态
/// </summary>
private const Int32 c_lsOwned = 0x00000001;
/// <summary>
/// 等待的线程数
/// </summary>
private const Int32 c_1Waiter = 0x00000002;
private Semaphore m_WaiterLock = new Semaphore(0, Int32.MaxValue);
#region 构造函数
/// <summary>
///
/// </summary>
public Optex() { }
#endregion
/// <summary>
/// 请求锁
/// </summary>
public void Enter()
{
Thread.BeginCriticalRegion();
while (true)
{
Int32 ls = InterlockedOr(ref m_LockState, c_lsOwned);
//自由状态
if ((ls & c_lsOwned) == c_lsFree) return;
// 增加等待的线程数
if (IfThen(ref m_LockState, ls, ls + c_1Waiter))
{
m_WaiterLock.WaitOne();
}
}
}
public void Exit()
{
// 释放琐
Int32 ls = InterlockedAnd(ref m_LockState, ~c_lsOwned);
//无等待的线程
if (ls == c_lsOwned)
{
}
else
{
ls &= ~c_lsOwned;
if (IfThen(ref m_LockState, ls & ~c_lsOwned, ls - c_1Waiter))
{
m_WaiterLock.Release(1);
}
else
{
}
}
Thread.EndCriticalRegion();
}
#region 原子化操作
/// <summary>
/// 与操作
/// </summary>
/// <param name="target"></param>
/// <param name="with"></param>
/// <returns></returns>
private static Int32 InterlockedAnd(ref Int32 target, Int32 with)
{
Int32 i, j = target;
do
{
i = j;
j = Interlocked.CompareExchange(ref target, i & with, i);
} while (i != j);
return j;
}
/// <summary>
/// 或操作
/// </summary>
/// <param name="target"></param>
/// <param name="with"></param>
/// <returns></returns>
private static Int32 InterlockedOr(ref Int32 target, Int32 with)
{
Int32 i, j = target;
do
{
i = j;
j = Interlocked.CompareExchange(ref target, i | with, i);
} while (i != j);
return j;
}
#endregion
private static Boolean IfThen(ref Int32 val, Int32 @if, Int32 then)
{
return (Interlocked.CompareExchange(ref val, @then, @if) == @if);
}
private static Boolean IfThen(ref Int32 val, Int32 @if, Int32 then, out Int32 prevVal)
{
prevVal = Interlocked.CompareExchange(ref val, @then, @if);
return (prevVal == @if);
}
/// <summary>
/// 释放资源
/// </summary>
public void Dispose()
{
if (m_WaiterLock != null)
{
m_WaiterLock.Close();
m_WaiterLock = null;
}
}
}
}
对于上面的这个代码,我晕眩了好一段时间,不过当我真正理解的时候,从晕眩中学到了做多线程编程应该具备的思维方式。