• 技术文章 >后端开发 >C#.Net教程

    从0自学C#13--子类和父类方法的锁对象问题

    黄舟黄舟2017-02-04 11:14:54原创499
    调用父类方法时,如何与子类方法,在锁对象不是同一个实例下,能线程安全,请见下面三种情况。

    case1:

    如下代码,在调用父类的方法时,和子类的方法,发生线程安全问题。原因的锁对象的实例不是同一个。

    using System;using System.Collections.Generic;
    using System.Linq;using System.Text;
    using System.Threading.Tasks;using System.Threading;
    
    namespace ForTest//check the lock object for thread safety{
        class Program
        {        static void Main(string[] args)
            {
                son myson = new son();
                Parallel.For(0, 5, (int i) =>
                 {
                     myson.methodA();
                     myson.methodC();
                 });
                Console.ReadKey();
            }
        }    public class grandfather
        {        //protected static object syncRoot = new object();
        }    public class father:grandfather
        {        private static object syncRoot = new object();        
    protected int cont = 0;        public virtual bool methodA()
            {            lock (syncRoot)
                {
                    cont++;
                    Thread.Sleep(1000);
                    Console.WriteLine("cout++ is " + cont);                
    return true;
                }
            }        public virtual bool methodB()
            {            lock (syncRoot)
                {                return true;
                }
            }
        }    public class son:father
        {        private static object syncRoot = new object();        
    public bool methodC()
            {            lock (syncRoot)
                {
                    cont += 2;
                    Thread.Sleep(2000);
                    Console.WriteLine("cont += 2 is " + cont);                
    return true;
                }
            }
        }
    }

    输出:

    cout++ is 1
    cout++ is 4
    cont += 2 is 5
    cout++ is 5
    cout++ is 8
    cont += 2 is 9
    cout++ is 11
    cont += 2 is 11
    cont += 2 is 13
    cont += 2 is 15

    case2:

    case1的解决方法是,在父类初始化锁对象,让子类继承。这样就线程安全了。如下。

    using System;using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Threading;
    
    namespace ForTest//check the lock object for thread safety{
        class Program
        {        static void Main(string[] args)
            {
                son myson = new son();
                Parallel.For(0, 5, (int i) =>
                 {
                     myson.methodA();
                     myson.methodC();
                 });
                Console.ReadKey();
            }
        }    public class grandfather
        {        protected static object syncRoot = new object();
        }    public class father:grandfather
        {        protected int cont = 0;        public virtual bool methodA()
            {            lock (syncRoot)
                {
                    cont++;
                    Thread.Sleep(1000);
                    Console.WriteLine("cout++ is " + cont);                return true;
                }
            }        public virtual bool methodB()
            {            lock (syncRoot)
                {                return true;
                }
            }
        }    public class son:father
        {        public bool methodC()
            {            lock (syncRoot)
                {
                    cont += 2;
                    Thread.Sleep(2000);
                    Console.WriteLine("cont += 2 is " + cont);                return true;
                }
            }
        }
    }

    输出:

    cout++ is 1
    cout++ is 2
    cont += 2 is 4
    cout++ is 5
    cout++ is 6
    cout++ is 7
    cont += 2 is 9
    cont += 2 is 11
    cont += 2 is 13
    cont += 2 is 15

    case3:

    当然有些特殊情况下,子类硬要重新实例化一个锁对象。如何避免上面第一种线程安全问题发生?需要:

    子类加锁重写父类分方法(如果父类methodA是虚方法)

    或者

    new一下(如果父类methodA是实例方法)。

    using System;using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Threading;
    
    namespace ForTest//check the lock object for thread safety{
        class Program
        {        static void Main(string[] args)
            {
                son myson = new son();
                Parallel.For(0, 5, (int i) =>
                 {
                     myson.methodA();
                     myson.methodC();
                 });
                Console.ReadKey();
            }
        }    public class grandfather
        {        protected static object syncRoot = new object();
        }    public class father:grandfather
        {        protected int cont = 0;        public virtual bool methodA()
            {            lock (syncRoot)
                {
                    cont++;
                    Thread.Sleep(1000);
                    Console.WriteLine("cout++ is " + cont);                return true;
                }
            }        public virtual bool methodB()
            {            lock (syncRoot)
                {                return true;
                }
            }
        }    public class son:father
        {        private static object sync = new object();        public override bool methodA()//重写
            {            lock (sync)
                {                return base.methodA();
                }
            }        public bool methodC()
            {            lock (sync)
                {
                    cont += 2;
                    Thread.Sleep(2000);
                    Console.WriteLine("cont += 2 is " + cont);                return true;
                }
            }
        }
    }

     public new bool methodA()\\new一下
            {            lock (sync)
                {                return base.methodA();
                }
            }

    输出:

    cout++ is 1
    cout++ is 2
    cont += 2 is 4
    cout++ is 5
    cout++ is 6
    cout++ is 7
    cont += 2 is 9
    cont += 2 is 11
    cont += 2 is 13
    cont += 2 is 15

    以上就是 从0自学C#13--子类和父类方法的锁对象问题的内容,更多相关内容请关注PHP中文网(m.sbmmt.com)!

    声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn核实处理。
    上一篇:从0自学C#12--线程同步解决方法汇总以及优缺点 下一篇:C++ 中字符串的使用

    相关文章推荐

    • c语言中形参的缺省存储类别是什么• C++设计模式浅识装饰模式• C++中内存泄漏的检测• C#的多线程机制初探(3)• 【c#教程】C# 预处理器指令

    全部评论我要评论

  • 取消发布评论发送
  • 1/1

    PHP中文网