29.3 用户模式构造

29.3.1 易变构造

当线程通过共享内存互相通信时,调用Volatile.Write来写入最后一个值,调用Volatile.Read来读取第一个值

    public class ThreadsSharingData
    {
        private volatile int flag = 0;
        private int value = 0;
        public void Thread1()
        {
            //注意在将1写入flag之前,必须先将5写入value
            value = 5;
            flag = 1;
        }
        public void Thread2()
        {
            //注意在value必须在读取了flag之后才能读取
            if (flag == 1)
                Console.WriteLine(value);
        }
    }

 29.3.2 互锁构造

    internal sealed class AsyncCoordinator
    {
        private int m_opCount = 1;
        private int m_statusReported = 0;
        private Action<CoordinatorStatus> m_callback;
        private Timer m_timer;

        public void AboutToBegin(int opsToAdd = 1)
        {
            Interlocked.Add(ref m_opCount, opsToAdd);
        }

        public void JuseEnded()
        {
            if (Interlocked.Decrement(ref m_opCount) == 0)
                ReportStatus(CoordinatorStatus.AllDone);
        }

        public void AllBegun(Action<CoordinatorStatus> callback, int timeout = Timeout.Infinite)
        {
            m_callback = callback;
            if (timeout != Timeout.Infinite)
                m_timer = new Timer(TimeExpired, null, timeout, Timeout.Infinite);
            JuseEnded();
        }

        private void TimeExpired(object o)
        {
            ReportStatus(CoordinatorStatus.Timeout);
            ReportStatus(CoordinatorStatus.Cancel);
        }

        private void ReportStatus(CoordinatorStatus status)
        {
            if (Interlocked.Exchange(ref m_statusReported, 1) == 0)
                m_callback(status);
        }

        public enum CoordinatorStatus
        {
            AllDone, Timeout, Cancel
        }
    }

 29.3.3 实现简单的自旋锁

    class Program
    {
        private static SimpleSpinLock ssl = new SimpleSpinLock();
        static void Main()
        {
            ssl.Enter();
            //一次只有一个线程才能进入这里访问资源
            ssl.Leave();

            Console.ReadKey();
        }
    }
    internal struct SimpleSpinLock
    {
        private int m_resourceInuse;    //0=false,1=true
        public void Enter()
        {
            while (true)
            {
                //总是将资源设置为正在使用
                //只有未使用变成正在使用才会返回
                if (Interlocked.Exchange(ref m_resourceInuse, 1) == 0)
                    return;
                //添加黑科技
            }
        }
        public void Leave()
        {
            Volatile.Write(ref m_resourceInuse, 0);
        }
    }

29.3.4 Interlocked anything

        delegate int Morpher<TResult, TArgument>(int startValue, TArgument argument, out TResult morphResult);

        private static TResult Morph<TResult, TArgument>(ref int target, TArgument argument, Morpher<TResult, TArgument> morpher)
        {
            TResult morphResult;
            int currentVal = target, startVal, desiredVal;
            do
            {
                startVal = currentVal;
                desiredVal = morpher(startVal, argument, out morphResult);
                currentVal = Interlocked.CompareExchange(ref target, desiredVal, startVal);

            }
            while (startVal != currentVal);
            return morphResult;
        }

        private static int Maximun(ref int target, int value)
        {
            int currentVal = target, startVal, desiredVal;
            //不要在循环中访问目标target,除非想要改变它时另一个线程也在动它
            do
            {
                //记录这一次循环的起始值startVal
                startVal = currentVal;
                //基于startVal和value计算desiredVal
                desiredVal = Math.Max(startVal, value);
                //注意:线程在这里可能被“抢占”,所以以下代码不是原子性的
                //if (target == startVal) target = desiredVal;
                //使用原子性的方法,返回在target在(可能)被方法修改之前的值
                currentVal = Interlocked.CompareExchange(ref target, desiredVal, startVal);
            }
            //如果target的值在这一次循环迭代中被其它线程改变,就重复
            while (startVal != currentVal);
            return desiredVal;
        }
原文地址:https://www.cnblogs.com/kikyoqiang/p/10211988.html