• 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;
            }
  • 相关阅读:
    APIO2018 题解
    【THUWC2017】在美妙的数学王国中畅游(bzoj5020)
    【bzoj3270】博物馆
    【库存】NOI笔试习题集
    装饰器
    异常
    类的详解
    函数
    流程控制
    运算符
  • 原文地址:https://www.cnblogs.com/kikyoqiang/p/10211988.html
Copyright © 2020-2023  润新知