欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

日记(2018-11-07)

程序员文章站 2022-04-14 10:17:00
2018 11 07日记 概览 今日立冬, 信息时代带来的焦躁让学习无法深入, 所以打算以写日记的形式戒掉焦躁, 重拾醉心学习的状态. Synchronized与SyncRoot技术同步线程数据 Serializable特性作用 RPC(远程方法调用) 数据同步 在多个线程*享数据, 很容易出现 ......

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

延申阅读

  • 并发集合类型

脚注