当前位置: 移动技术网 > IT编程>开发语言>.net > 日记(2018-11-07)

日记(2018-11-07)

2018年11月08日  | 移动技术网IT编程  | 我要评论

天木纯,成功一试灵,高峻峰

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 今天太晚, 没时间再写了, 以后补上.

延申阅读

  • 并发集合类型

脚注

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网