調用父類方法時,如何與子類方法,在鎖對象不是同一個執行個體下,能安全執行緒,請見下面三種情況。
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--子類和父類方法的鎖對象問題的內容,更多相關內容請關注topic.alibabacloud.com(www.php.cn)!