日记(2018-11-07)

# 2018-11-07日记 ## 概览 今日立冬, 信息时代带来的焦躁让学习无法深入, 所以打算以写日记的形式戒掉焦躁, 重拾醉心学习的状态. - Synchronized与SyncRoot技术同步线程数据 - Serializable特性作用 - RPC(远程方法调用) ## 数据同步 > 在多个线程中共享数据, 很容易出现`争用条件`和`死锁` ### 争用条件(RaceCondition) 设想如下代码和步骤: 1. 第一个线程程序执行到`if`语句, 假设此时`_state`等于5, 条件为真 2. 进入`if`语句之后, 它就被其他线程抢占, 调度器运行另一个线程 3. 在另一个线程中某些代码将`_state`的值改变为`6` 4. 第一个线程再次被调度, 此时`_state`等于`6`, 在执行完`_state++`语句后, `_state`将等于7 5. 提示: 实际上 `_state++`的操作将从内存中获取值,给该值增加`1`, 然后再写回内存. 这些操作都可能被线程调度器打断, 造成线程不安全! ```c# public void ChangeState() { if (_state == 5) { _state++; } } ``` 解决方法是给`_state`对象加锁, 将锁定对象设置为线程安全对象, 一个线程锁住了`_state`对象, 其他线程就必须等待该锁定解除. 但是`_state`是`值对象`, 不是`引用对象`, `lock`只能锁住`引用对象`, 因为锁住一个值的副本毫无意义. 那么就需要用一个对象来同步.代码如下: ```c# 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`以确保线程安全的操作集合. ```c# 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** 确保再一个实例中, 不管再代码的任何位置调用, 返回的都是同一个对象, 它是唯一的. ```c# 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 今天太晚, 没时间再写了, 以后补上. ## 延申阅读 - 并发集合类型 ## 脚注 - [C# Synchronized 和 SyncRoot 实现线程同步的源码分析及泛型集合的线程安全访问](http://www.cnblogs.com/baoku/p/4818612.html#undefined) - [C# Serializable的作用](https://www.cnblogs.com/eedc/p/7908701.html)
posted @ 2018-11-07 22:44 学友2000 阅读(...) 评论(...) 编辑 收藏