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;
        }
复制代码

 

posted @   一只桔子2233  阅读(208)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律
点击右上角即可分享
微信分享提示