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

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

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);                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–子类和父类方法的锁对象问题的内容,更多相关内容请关注PHP中文网(www.php.cn)!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/1432042.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2025年12月17日 06:09:25
下一篇 2025年12月17日 06:09:42

相关推荐

发表回复

登录后才能评论
关注微信