日记(2018-11-07)
程序员文章站
2022-04-14 10:17:00
2018 11 07日记 概览 今日立冬, 信息时代带来的焦躁让学习无法深入, 所以打算以写日记的形式戒掉焦躁, 重拾醉心学习的状态. Synchronized与SyncRoot技术同步线程数据 Serializable特性作用 RPC(远程方法调用) 数据同步 在多个线程*享数据, 很容易出现 ......
2018-11-07日记
概览
今日立冬, 信息时代带来的焦躁让学习无法深入, 所以打算以写日记的形式戒掉焦躁, 重拾醉心学习的状态.
- synchronized与syncroot技术同步线程数据
- serializable特性作用
- rpc(远程方法调用)
数据同步
在多个线程*享数据, 很容易出现
争用条件
和死锁
争用条件(racecondition)
设想如下代码和步骤:
- 第一个线程程序执行到
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++; } } } }
死锁(deadlock)
过多的锁会导致线程都再等待对方解除锁定, 出现死锁. 所以再程序设计一开始就需要考虑到死锁问题, 设计好锁定顺序和锁定超时时间.
synchronized与syncroot技术
再.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; } }
serializable特性和rpc
todo: #1 今天太晚, 没时间再写了, 以后补上.
延申阅读
- 并发集合类型