线程、同步与锁——Mutex想说爱你不容易
還是先舉一個(gè)簡(jiǎn)單的例子,來(lái)說(shuō)明一下這個(gè)東西:
?
???public?class?ThreadMutex????{
????????public?void?Test()
????????{
????????????Thread?t1?=?new?Thread(Thread1);
????????????Thread?t2?=?new?Thread(Thread2);
????????????t1.Start();
????????????t2.Start();
????????}
????????public?void?Thread1()
????????{
????????????Mutex?m?=?new?Mutex(false,?"test");
????????????bool?b2?=?m.WaitOne();
????????????Console.WriteLine("Thread1?get?the?mutex?:?"?+?b2);
????????????Thread.Sleep(10000);
????????????m.ReleaseMutex();
????????}
????????public?void?Thread2()
????????{
????????????Mutex?m?=?new?Mutex(false,?"test");
????????????bool?b2?=?m.WaitOne();
????????????Console.WriteLine("Thread2?get?the?mutex?:?"?+?b2);
????????????Thread.Sleep(1000);
????????????m.ReleaseMutex();
????????????
????????}
}
恩,Thread1中Mutex.WaitOne()后,就想到與Thread1拿到了Mutex所有權(quán),這時(shí)Thread2得到了同樣的Mutex,然后Mutex.WaitOne(),也想拿到Mutex的所有權(quán),這時(shí)就必須等待了。這里只需要兩點(diǎn)就能明白什么是Mutex了:
1.?? Mutex是一個(gè)令牌,當(dāng)一個(gè)線程拿到這個(gè)令牌時(shí)運(yùn)行,另外想拿到令牌的線程就必須等待,直到拿到令牌的線程釋放令牌。沒(méi)有所有權(quán)的線程是無(wú)法釋放令牌的。
2.?? Mutex(false,”string”)中的string是令牌的關(guān)鍵,或者可以叫令牌名,因?yàn)镸utex是跨進(jìn)程的,整個(gè)系統(tǒng)中只會(huì)有唯一的令牌存在所以,也就是說(shuō)你在一個(gè)應(yīng)用程序中的一個(gè)線程中得到了Mutex的所有權(quán),那在另外一個(gè)線程中的另外的線程想得到他就必須要等待。
要弄清楚Mutex就還需要弄清楚兩個(gè)很重要的問(wèn)題:
1.那就是Mutex是調(diào)用的Win32 的API?
HANDLE CreateMutex(
?? LPSECURITY_ATTRIBUTES lpMutexAttributes,
?? BOOL bInitialOwner,
?? LPCTSTR lpName
);
這就是他為什么能跨進(jìn)程訪問(wèn)的原因,正是由于它使用P/Invoke,他的效率問(wèn)題就凸現(xiàn)出來(lái),明顯不如Monitor之類(lèi)的快,用的時(shí)候還需多多斟酌。
?
下面放一個(gè)Mutex的簡(jiǎn)單實(shí)現(xiàn),看看Mutex在.net下是如何實(shí)現(xiàn)的。
?2.Mutex的生命周期,這個(gè)問(wèn)題讓我郁悶了很久,因?yàn)椴惶私釳utex的機(jī)制,使得我也沒(méi)法弄清楚到底能活多長(zhǎng)時(shí)間,這也是AbandonedMutexException經(jīng)常會(huì)出現(xiàn)的原因。還是先來(lái)看一段程序:
?
??public?class?ThreadMutex????{
????????public?void?Test()
????????{
????????????Thread?t1?=?new?Thread(Thread1);
????????????Thread?t2?=?new?Thread(Thread2);
????????????t1.Start();
????????????t2.Start();
????????}
????????public?void?Thread1()
????????{
????????????Mutex?m?=?new?Mutex(false,?"test");
????????????bool?b2?=?m.WaitOne();
????????????Console.WriteLine("Thread1?get?the?mutex?:?"?+?b2);
????????}
????????public?void?Thread2()
????????{
????????????Thread.Sleep(10);//保證Thread1執(zhí)行完
????????????Mutex?m?=?new?Mutex(false,?"test");
????????????bool?b2=m.WaitOne();
????????????Console.WriteLine(b2);
????????????m.ReleaseMutex();
????????}
}
在Thread2中的WaitOne()方法就會(huì)報(bào)錯(cuò)了,AbandonedMutexException,原因就是Thread1拿到了Mutex后沒(méi)有釋放,Thread1就結(jié)束了,這樣Mutex成了被拋棄的地孩子了,呵呵。但是如果垃圾收集了,就不一樣咯。代碼稍微修改了一下:
?
??public?class?ThreadMutex????{
????????public?void?Test()
????????{
????????????Thread?t1?=?new?Thread(Thread1);
????????????Thread?t2?=?new?Thread(Thread2);
????????????t1.Start();
????????????t2.Start();
????????}
????????public?void?Thread1()
????????{
????????????Mutex?m?=?new?Mutex(false,?"test");
????????????bool?b2?=?m.WaitOne();
????????????Console.WriteLine("Thread1?get?the?mutex?:?"?+?b2);
????????}
????????public?void?Thread2()
????????{
????????????Thread.Sleep(10);//保證Thread1執(zhí)行完
????????????GC.Collect();
????????????GC.WaitForPendingFinalizers();
????????????bool?b1;
????????????Mutex?m?=?new?Mutex(false,?"test",out?b1);
????????????Console.WriteLine(b1);
????????????bool?b2=m.WaitOne();
????????????Console.WriteLine(b2);
????????????m.ReleaseMutex();
????????????
????????}
????}
結(jié)果是:
Thread1 get the mutex : True
True
True
Thread2里面的Mutex是新創(chuàng)建的,呵呵,這里面的玄妙自己體會(huì)吧。
?
最后要說(shuō)一下的是Mutex的訪問(wèn)和window訪問(wèn)文件的機(jī)制基本上是一樣的,window訪問(wèn)對(duì)象和訪問(wèn)文件使用的是同樣的安全機(jī)制(雖然我還沒(méi)看懂)。總結(jié)
以上是生活随笔為你收集整理的线程、同步与锁——Mutex想说爱你不容易的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 将iphone中的照片同步到电脑
- 下一篇: 网线有问题?