您好,登錄后才能下訂單哦!
本篇內(nèi)容介紹了“C#怎么使用LOCK實(shí)現(xiàn)線程同步”的有關(guān)知識,在實(shí)際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細(xì)閱讀,能夠?qū)W有所成!
線程安全概念:線程安全是指在當(dāng)一個(gè)線程訪問該類的某個(gè)數(shù)據(jù)時(shí),進(jìn)行保護(hù),其他線程不能進(jìn)行訪問直到該線程讀取完,其他線程才可使用。不會出現(xiàn)數(shù)據(jù)不一致或者數(shù)據(jù)污染。
線程有可能和其他線程共享一些資源,比如,內(nèi)存,文件,數(shù)據(jù)庫等。當(dāng)多個(gè)線程同時(shí)讀寫同一份共享資源的時(shí)候,可能會引起沖突。這時(shí)候,我們需要引入線程“同步”機(jī)制,即各位線程之間要有個(gè)先來后到,不能一窩蜂擠上去搶作一團(tuán)。線程同步的真實(shí)意思和字面意思恰好相反。線程同步的真實(shí)意思,其實(shí)是“排隊(duì)”:幾個(gè)線程之間要排隊(duì),一個(gè)一個(gè)對共享資源進(jìn)行操作,而不是同時(shí)進(jìn)行操作。
下面將通過簡單的四個(gè)案例進(jìn)行對比,來講解LOCK的實(shí)現(xiàn)線程同步使用。
首先創(chuàng)建兩個(gè)線程,兩個(gè)線程執(zhí)行同一個(gè)方法,代碼如下:
class Program { static void Main(string[] args) { Thread threadA = new Thread(ThreadMethod); //執(zhí)行的必須是無返回值的方法 threadA.Name = "threadA"; Thread threadB = new Thread(ThreadMethod); //執(zhí)行的必須是無返回值的方法 threadB.Name = "threadB"; threadA.Start(); threadB.Start(); Console.ReadKey(); } public static void ThreadMethod(object parameter) { for (int i = 1; i <= 10; i++) { Console.WriteLine("我是:{0},我循環(huán){1}次", Thread.CurrentThread.Name, i); Thread.Sleep(1000);//休眠一秒 } } }
通過下面的執(zhí)行結(jié)果,可以很清楚的看到,兩個(gè)線程是在同時(shí)執(zhí)行ThreadMethod這個(gè)方法,這顯然不符合我們線程同步的要求。
執(zhí)行結(jié)果:
通過對上面代碼的修改如下:
class Program { static void Main(string[] args) { Program pro = new Program(); Thread threadA = new Thread(pro.ThreadMethod); threadA.Name = "threadA"; Thread threadB = new Thread(pro.ThreadMethod); threadB.Name = "threadB"; threadA.Start(); threadB.Start(); Console.ReadKey(); } public void ThreadMethod(object parameter) { lock (this) //添加lock關(guān)鍵字 { for (int i = 1; i <= 10; i++) { Console.WriteLine("我是:{0},我循環(huán){1}次", Thread.CurrentThread.Name, i); Thread.Sleep(1000);//休眠一秒 } } } }
執(zhí)行結(jié)果:
我們通過添加了 lock(this) {...}代碼,查看執(zhí)行結(jié)果實(shí)現(xiàn)了我們想要的線程同步需求。
但是我們知道this表示當(dāng)前類實(shí)例的本身,那么有這么一種情況,我們把需要訪問的方法所在的類型進(jìn)行兩個(gè)實(shí)例A和B,線程A訪問實(shí)例A的方法ThreadMethod,線程B訪問實(shí)例B的方法ThreadMethod,這樣的話還能夠達(dá)到線程同步的需求嗎?
修改后的代碼如下:
class Program { static void Main(string[] args) { Program pro1 = new Program(); Program pro2 = new Program(); Thread threadA = new Thread(pro1.ThreadMethod); threadA.Name = "threadA"; Thread threadB = new Thread(pro2.ThreadMethod); threadB.Name = "threadB"; threadA.Start(); threadB.Start(); Console.ReadKey(); } public void ThreadMethod(object parameter) { lock (this) //添加lock關(guān)鍵字 { for (int i = 1; i <= 10; i++) { Console.WriteLine("我是:{0},我循環(huán){1}次", Thread.CurrentThread.Name, i); Thread.Sleep(1000);//休眠一秒 } } } }
執(zhí)行結(jié)果:
我們會發(fā)現(xiàn),線程又沒有實(shí)現(xiàn)同步了!lock(this)對于這種情況是不行的!
通過對上面代碼再次進(jìn)行如下修改:
class Program { private static object obj = new object(); static void Main(string[] args) { Program pro1 = new Program(); Program pro2 = new Program(); Thread threadA = new Thread(pro1.ThreadMethod); threadA.Name = "threadA"; Thread threadB = new Thread(pro2.ThreadMethod); threadB.Name = "threadB"; threadA.Start(); threadB.Start(); Console.ReadKey(); } public void ThreadMethod(object parameter) { lock (obj) //添加lock關(guān)鍵字 { for (int i = 1; i <= 10; i++) { Console.WriteLine("我是:{0},我循環(huán){1}次", Thread.CurrentThread.Name, i); Thread.Sleep(1000);//休眠一秒 } } } }
執(zhí)行結(jié)果:
通過查看執(zhí)行結(jié)果。會發(fā)現(xiàn)代碼實(shí)現(xiàn)了我們的需求。
那么 lock(this) 和lock(Obj)有什么區(qū)別呢?
lock(this) 鎖定 當(dāng)前實(shí)例對象,如果有多個(gè)類實(shí)例的話,lock鎖定的只是當(dāng)前類實(shí)例,對其它類實(shí)例無影響。所有不推薦使用。
lock(typeof(Model))鎖定的是model類的所有實(shí)例。
lock(obj)鎖定的對象是全局的私有化靜態(tài)變量。外部無法對該變量進(jìn)行訪問。
lock 確保當(dāng)一個(gè)線程位于代碼的臨界區(qū)時(shí),另一個(gè)線程不進(jìn)入臨界區(qū)。如果其他線程試圖進(jìn)入鎖定的代碼,則它將一直等待(即被阻止),直到該對象被釋放。
所以,lock的結(jié)果好不好,還是關(guān)鍵看鎖的誰,如果外邊能對這個(gè)誰進(jìn)行修改,lock就失去了作用。所以一般情況下,使用私有的、靜態(tài)的并且是只讀的對象
“C#怎么使用LOCK實(shí)現(xiàn)線程同步”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識可以關(guān)注億速云網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實(shí)用文章!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。