任务同步一

首先要避免同步,最好是不要在线程之间共享数据。如果必须要共享数据,就需要用到同步技术。

使用线程容易出现的两个问题:争用条件和死锁。

如果两个或多个线程访问相同的对象,并且对共享状态的访问没有同步,就会出现争用条件。

如下案例,执行会出现征用条件的程序断言

    public class StateObject
    {
        private int _state = 5;
        public void ChangeState(int loop)
        {
            if (_state == 5)
            {
                _state++;
            }
            Trace.Assert(_state == 6, $"{loop}次循环后出现争用条件");
            _state = 5;
        }
    }
    public class SampleTask
    {
        public void RaceCondition(object o)
        {
            Trace.Assert(o is StateObject, "o必须是StateObject类型");
            StateObject state = o as StateObject;
            int i = 0;
            while (true)
            {
                state.ChangeState(i++);
            }

        }
        public void RaceConditions()
        {
            var state = new StateObject();
            for (int i = 0; i < 2; i++)
            {
                Task.Run(() => new SampleTask().RaceCondition(state));
            }
        }
    }
//调用RaceConditions方法,会出现断言

上述案例,只要在while循环体里面对StateObject 对象加入lock关键字就可以解决争用条件。

死锁:过多的锁定容易出现麻烦。在死锁中,至少有两个线程被挂起,并等待对方解除锁定。由于两个线程都在等待对方,就出现了死锁,线程将无线等待下去。

    public class StateObject
    {
        private int _state = 5;
        private object sync = new object();
        public void ChangeState(int loop)
        {
            lock (sync)
            {
                if (_state == 5)
                {
                    _state++;
                }
                Trace.Assert(_state == 6, $"{loop}次循环后出现争用条件");
            }
            _state = 5;
        }
    }
    public class SampleTask
    {
        private StateObject _s1;
        private StateObject _s2;
        public SampleTask(StateObject s1, StateObject s2)
        {
            _s1 = s1;
            _s2 = s2;
        }
        public void Deadlock1()
        {
            int i = 0;
            while (true)
            {
                lock (_s1)
                {
                    lock (_s2)
                    {
                        _s1.ChangeState(i);
                        _s2.ChangeState(i++);
                        Console.WriteLine($"still running, {i}");
                    }
                }
            }
        }

        public void Deadlock2()
        {
            int i = 0;
            while (true)
            {
                lock (_s2)
                {
                    lock (_s1)
                    {
                        _s1.ChangeState(i);
                        _s2.ChangeState(i++);
                        Console.WriteLine($"still running, {i}");
                    }
                }
            }
        }

        //public void RaceCondition(object o)
        //{
        //    Trace.Assert(o is StateObject, "o必须是StateObject类型");
        //    StateObject state = o as StateObject;
        //    int i = 0;
        //    while (true)
        //    {
        //        state.ChangeState(i++);
        //    }

        //}
        //public void RaceConditions()
        //{
        //    var state = new StateObject();
        //    for (int i = 0; i < 2; i++)
        //    {
        //        Task.Run(() => new SampleTask().RaceCondition(state));
        //    }
        //}
    }
//调用
            var state1 = new StateObject();
            var state2 = new StateObject();
            new Task(new SampleTask(state1,state2).Deadlock1).Start();
            new Task(new SampleTask(state1, state2).Deadlock2).Start();
            Console.ReadLine();

lock语句和线程安全:

    public class SharedState
    {
        //public int State { get; set; }
        private int _state = 0;
        private object _syncRoot = new object();
        public int State => _state;
        public int IncrementState()
        {
            lock (_syncRoot)
            {
                return ++_state;
            }
        }
    }
    public class Job
    {
        private SharedState _sharedState;
        public Job(SharedState sharedState)
        {
            _sharedState = sharedState;
        }
        public void DoTheJob()
        {
            for (int i = 0; i < 50000; i++)
            {
                _sharedState.IncrementState();
            }
        }
    }
//调用方式
            int numTasks = 20;
            var state = new SharedState();
            var tasks = new Task[numTasks];
            for (int i = 0; i < numTasks; i++)
            {
                tasks[i] = Task.Run(() => new Job(state).DoTheJob());
            }
            Task.WaitAll(tasks);
            Console.WriteLine($"summarized {state.State}");
            Console.ReadLine();

Interlocked类用于使变量的简单语句原子化,Interlocked类提供了以线程安全的方式递增、递减、交换和读取值的方法。

Interlocked在处理简单的原子化语句性能优于lock语句;看如下案例(递减:Decrement;交换:Exchange;读取:Read)

        public int IncrementState()
        {
            //lock (_syncRoot)
            //{
            //    return _state++;
            return Interlocked.Increment(ref _state);
            //}
        }
        public void DoTheJob()
        {
            for (int i = 0; i < 50000000; i++)
            {
                _sharedState.IncrementState();
            }
        }
//测试
            Stopwatch sw = new Stopwatch();
            sw.Start();
            int numTasks = 20;
            var state = new SharedState();
            var tasks = new Task[numTasks];
            for (int i = 0; i < numTasks; i++)
            {
                tasks[i] = Task.Run(() => new Job(state).DoTheJob());
            }
            Task.WaitAll(tasks);
            sw.Stop();
            Console.WriteLine($"summarized {state.State}");
            Console.WriteLine("所用时间:" + sw.Elapsed.TotalSeconds+"秒");
            Console.ReadLine();

下章讲述后续同步类的使用

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

双叶红于二月花

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值