zoukankan      html  css  js  c++  java
  • 日记(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, 然后再写回内存. 这些操作都可能被线程调度器打断, 造成线程不安全!
    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集合类型中, 比如HashtableArrayList都有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 今天太晚, 没时间再写了, 以后补上.

    延申阅读

    • 并发集合类型

    脚注

  • 相关阅读:
    dom4j 解析 xml文件1
    java 简单的动态代理例子
    标识接口的作用 (转)
    JAVA servlet输出IE6下乱码
    java时间操作函数汇总
    IE支持getElementsByClassName方法
    女朋友问我 LB 是谁?
    人类高质量 Java 学习路线【一条龙版】
    程序员作图工具和技巧,你 get 了么?
    3 分钟了解 JSON Schema
  • 原文地址:https://www.cnblogs.com/xueyoucd/p/9926311.html
Copyright © 2011-2022 走看看