/// <summary>
/// 无锁算法,如果多次冲突,这个算法不一定会比线程锁快
/// </summary>
public class DualCounter
{
public int A { get; set; }
public int B { get; set; }
public DualCounter(int a, int b)
{
A = a;
B = b;
}
public static DualCounter Increment(ref DualCounter counter)
{
DualCounter oldValue, newValue;
int i = 0;
do
{
oldValue = counter;
newValue = new DualCounter(oldValue.A + 1, oldValue.B + 1);
if(0!=i++)Console.WriteLine("线程冲突,重新赋值");
//如果conter 和 oldvalue相等则newValue替换counter,然后返回counter的值
} while (Interlocked.CompareExchange(ref counter, newValue, oldValue) != oldValue);
return newValue;
}
}
/// <summary>
/// 自旋锁,执行的保护区代码一定要非常快,要不然吃性能
/// 如果获取锁失败,调用 Thread.Yield(); 来通知系统,释放锁
/// </summary>
public class MySpinlock
{
static int _lock = 0;
// volatile static int _lock = 0;
static int _counterA = 0;
static int _counterB = 0;
static SpinLock _locks = new SpinLock();
public static void Exchange(ref int aocunter,int mnum)
{
bool lockTaken = false;
try
{
//获取锁
_locks.Enter(ref lockTaken);
//保护区开始
aocunter = mnum;
//解除保护
}
finally
{
//如果成功获取锁则释放
if (lockTaken)
{
_locks.Exit();
}
}
}
public static void IncrementCounters()
{
//改变_lock 的值为1
var spinWait = new SpinWait();
while(Interlocked.Exchange(ref _lock, 1) != 0)
{
//Thread.SpinWait(1);
spinWait.SpinOnce(); //如果单核心则使用sleep(0) 等待,反之使用轮询 SpinWait
}
//线程保护区域开始
++_counterA;
++_counterB;
//线程保护区域结束
Interlocked.Exchange(ref _lock, 0);
}
public static void GetCounters(out int A,out int B)
{
//改变_lock 的值为1
while (Interlocked.Exchange(ref _lock, 1) != 0)//Exchange使用了内存屏障,确保cpu能够观测到
//如果不使用Exchange可以使用 Interlocked.MemoryBarrier(内存屏障) 函数且_lock 加volatile 修饰来达到同样的效果
{
Thread.SpinWait(1);//自旋中,cpu根据自身特性,休息一定时钟周期,在x86架构的cpu中会使用pause汇编指令
}
//线程保护区域开始
A=_counterA++;
B=_counterB++;
//线程保护区域结束
//释放锁
Interlocked.Exchange(ref _lock, 0);
}
}
//互斥锁
public class MyMutex
{
static Mutex _lock = new Mutex(false, "Local\\test");//可以重复进入锁,但是锁会进行累积,但释放到0时才是真的释放锁
//Mutex 支持跨进程锁定,第二个参数传入"Local\"表示用一用户进程共享,"Global\"表示同一计算机进程共享,Global\test
// 如果进程获取了锁,另外一个进程获取同一个名称的锁需要等待,如果到退出都没释放,操作系统自行释放锁
static int _counterA = 0;
static int _counterB = 0;
public static void IncrementCounters()
{
//获取锁
_lock.WaitOne();
try
{
++_counterA;
++_counterB;
}
finally
{
//释放锁
_lock.ReleaseMutex();
}
}
}
//混合锁
public class MyMonitor
{
public MyMonitor()
{
}
static object _lock = new object();
static int _countA = 0;
public static void IncrementCounters()
{
object lockObj = _lock;
bool lockTaken = false;
try
{
Monitor.Enter(lockObj, ref lockTaken);
++_countA;
}
finally
{
if (lockTaken)
Monitor.Exit(lockObj);
}
}
public static void IncrementCounter()
{
lock (_lock)//混合锁的简单写法
{
++_countA;
}
}
// private static Semaphore _sema = new Semaphore(0,2,"Local\\test");//信号量,最小0,最大2,跨进程
//private static Semaphore _sema = new Semaphore(0,2);//信号量,最小0,最大2,跨进程
private static SemaphoreSlim _sema = new SemaphoreSlim(0, 2);//轻信号量,如果不用跨进程,则优先使用它
public static void Worker(object o)
{
while (true)
{
Console.WriteLine("线程" + o);
//减少信号量
//_sema.WaitOne();
_sema.Wait();
Console.WriteLine("wait One "+o);
}
}
public static void DoWorker()
{
for(var x = 0; x < 6; ++x)
{
var thread = new Thread(new ParameterizedThreadStart(Worker));
thread.IsBackground = true;
thread.Start(x);
}
while (true)
{
///添加两个信号量
_sema.Release(1);
Thread.Sleep(1000);
}
}
}