经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » C# » 查看文章
日记(2018-11-07)
来源:cnblogs  作者:学友2000  时间:2018/11/8 9:57:11  对本文有异议

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, 然后再写回内存. 这些操作都可能被线程调度器打断, 造成线程不安全!
  1. public void ChangeState()
  2. {
  3. if (_state == 5)
  4. {
  5. _state++;
  6. }
  7. }

解决方法是给_state对象加锁, 将锁定对象设置为线程安全对象, 一个线程锁住了_state对象, 其他线程就必须等待该锁定解除.

但是_state值对象, 不是引用对象, lock只能锁住引用对象, 因为锁住一个值的副本毫无意义. 那么就需要用一个对象来同步.代码如下:

  1. public class StateObject
  2. {
  3. private int _state = 5;
  4. private object sync = new object();
  5. public void ChangeState()
  6. {
  7. lock (sync)
  8. {
  9. if (_state == 5)
  10. {
  11. _state++;
  12. }
  13. }
  14. }
  15. }

死锁(Deadlock)

过多的锁会导致线程都再等待对方解除锁定, 出现死锁. 所以再程序设计一开始就需要考虑到死锁问题, 设计好锁定顺序和锁定超时时间.

Synchronized与SyncRoot技术

再.net集合类型中, 比如HashtableArrayList都有Synchronized静态方法和SyncRoot实力方法. 返回一个线程安全的SyncHashtable对象, 这个对象中的方法, 比如Add都会锁定SyncRoot以确保线程安全的操作集合.

  1. namespace SynchronizationSamples
  2. {
  3. public class Demo
  4. {
  5. public virtual bool IsSynchronized => false;
  6. public virtual void DoThis() {}
  7. public virtual void DoThat() {}
  8. public static Demo Synchronized(Demo d)
  9. {
  10. if (!d.IsSynchronized)
  11. {
  12. return new Synchronized(d);
  13. }
  14. return d;
  15. }
  16. }
  17. // 同步版本
  18. private class SynchronizedDemo: Demo
  19. {
  20. public override bool IsSynchronized => true;
  21. private object _syncRoot = new object();
  22. private Demo _d;
  23. public SynchronizedDemo(Demo d)
  24. {
  25. _d = d;
  26. }
  27. public override void DoThis()
  28. {
  29. lock (_syncRoot)
  30. {
  31. _d.DoThis();
  32. }
  33. }
  34. public override void DoThat()
  35. {
  36. lock (_syncRoot)
  37. {
  38. _d.DoThat();
  39. }
  40. }
  41. }
  42. }

SyncRoot

确保再一个实例中, 不管再代码的任何位置调用, 返回的都是同一个对象, 它是唯一的.

  1. public virtual object SyncRoot
  2. {
  3. get
  4. {
  5. if (this._syncRoot == null)
  6. {
  7. // Interlocked为多个线程共享的变量提供原子操作, 原子操作就是单线程操作
  8. Interlocked.CompareExchange(ref this._syncRoot, new object(), null);
  9. }
  10. return this._syncRoot;
  11. }
  12. }

Serializable特性和RPC

todo: #1 今天太晚, 没时间再写了, 以后补上.

延申阅读

  • 并发集合类型

脚注

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号