天木纯,成功一试灵,高峻峰
今日立冬, 信息时代带来的焦躁让学习无法深入, 所以打算以写日记的形式戒掉焦躁, 重拾醉心学习的状态.
在多个线程中共享数据, 很容易出现
争用条件
和死锁
设想如下代码和步骤:
if
语句, 假设此时_state
等于5, 条件为真if
语句之后, 它就被其他线程抢占, 调度器运行另一个线程_state
的值改变为6
_state
等于6
, 在执行完_state++
语句后, _state
将等于7_state++
的操作将从内存中获取值,给该值增加1
, 然后再写回内存. 这些操作都可能被线程调度器打断, 造成线程不安全!public void changestate() { if (_state == 5) { _state++; } }
解决方法是给_state
对象加锁, 将锁定对象设置为线程安全对象, 一个线程锁住了_state
对象, 其他线程就必须等待该锁定解除.
但是_state
是值对象
, 不是引用对象
, lock
只能锁住引用对象
, 因为锁住一个值的副本毫无意义. 那么就需要用一个对象来同步.代码如下:
public class stateobject { private int _state = 5; private object sync = new object(); public void changestate() { lock (sync) { if (_state == 5) { _state++; } } } }
过多的锁会导致线程都再等待对方解除锁定, 出现死锁. 所以再程序设计一开始就需要考虑到死锁问题, 设计好锁定顺序和锁定超时时间.
再.net集合类型中, 比如
hashtable
和arraylist
都有synchronized
静态方法和syncroot
实力方法. 返回一个线程安全的synchashtable
对象, 这个对象中的方法, 比如add
都会锁定syncroot
以确保线程安全的操作集合.
namespace synchronizationsamples { public class demo { public virtual bool issynchronized => false; public virtual void dothis() {} public virtual void dothat() {} public static demo synchronized(demo d) { if (!d.issynchronized) { return new synchronized(d); } return d; } } // 同步版本 private class synchronizeddemo: demo { public override bool issynchronized => true; private object _syncroot = new object(); private demo _d; public synchronizeddemo(demo d) { _d = d; } public override void dothis() { lock (_syncroot) { _d.dothis(); } } public override void dothat() { lock (_syncroot) { _d.dothat(); } } } }
syncroot
确保再一个实例中, 不管再代码的任何位置调用, 返回的都是同一个对象, 它是唯一的.
public virtual object syncroot { get { if (this._syncroot == null) { // interlocked为多个线程共享的变量提供原子操作, 原子操作就是单线程操作 interlocked.compareexchange(ref this._syncroot, new object(), null); } return this._syncroot; } }
todo: #1 今天太晚, 没时间再写了, 以后补上.
如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复
Net Core Web Api项目与在NginX下发布的方法
asp.net core3.1 引用的元包dll版本兼容性问题解决方案
IdentityServer4实现.Net Core API接口权限认证(快速入门)
ASP.NET Core MVC通过IViewLocationExpander扩展视图搜索路径的实现
网友评论