• 欢迎访问搞代码网站,推荐使用最新版火狐浏览器和Chrome浏览器访问本网站!
  • 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏搞代码吧

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

c# 搞代码 4年前 (2022-01-09) 34次浏览 已收录 0个评论

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

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 1cout++ is 4cont += 2 is 5cout++ is 5cout++ is 8cont += 2 is 9cout++ is 11cont += 2 is 11cont += 2 is 13cont += 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 1cout++ is 2cont += 2 is 4cout++ is 5cout++ is 6cout++ is 7cont += 2 is 9cont += 2 is 11cont += 2 is 13cont += 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);               <em style="color:transparent">本文来源gao.dai.ma.com搞@代*码#网</em> 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 1cout++ is 2cont += 2 is 4cout++ is 5cout++ is 6cout++ is 7cont += 2 is 9cont += 2 is 11cont += 2 is 13cont += 2 is 15

以上就是 从0自学C#13–子类和父类方法的锁对象问题的内容,更多相关内容请关注搞代码(www.gaodaima.com)!


搞代码网(gaodaima.com)提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发送到邮箱[email protected],我们会在看到邮件的第一时间内为您处理,或直接联系QQ:872152909。本网站采用BY-NC-SA协议进行授权
转载请注明原文链接:从0自学C#13–子类和父类方法的锁对象问题

喜欢 (0)
[搞代码]
分享 (0)
发表我的评论
取消评论

表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址