>백엔드 개발 >C#.Net 튜토리얼 >0에서 C#13 자가 학습 - 하위 클래스 및 상위 클래스 메서드의 개체 잠금 문제

0에서 C#13 자가 학습 - 하위 클래스 및 상위 클래스 메서드의 개체 잠금 문제

黄舟
黄舟원래의
2017-02-04 11:14:541240검색

调用父类方法时,如何与子类方法,在锁对象不是同一个实例下,能线程安全,请见下面三种情况。

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中文网(www.php.cn)!


성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.