死鎖的問題出現

cpu分給每個線程的時間片是隨機的并且有好多都是多個線程共用一個資源,比如現在我們很多的搶火車賣票,火車票是一定的,但賣火車票的窗口到處都有,每個窗口就相當于一個線程,這么多的線程共用所有的火車票這個資源。如果在一個時間點上,兩個線程同時使用這個資源,那他們取出的火車票是一樣的(座位號一樣),這樣就會給乘客造成麻煩。比如下面程序:

 

package com.dr.runnable2;

class TicketSouce implements Runnable

{

//票的總數

private int ticket=10;

public void run()

{

for(int i=1;i<50;i++)

{

if(ticket>0)

{

//休眠1s秒中,為了使效果更明顯,否則可能出不了效果

try {

Thread.sleep(1000);

} catch (InterruptedException e) {

e.printStackTrace();

}

System.out.println(Thread.currentThread().getName()+”號窗口賣出”+this.ticket–+”號票”);

}

}

}

}

public class Test {

public static void main(String args[])

{

TicketSouce mt=new TicketSouce();

//基于火車票創建三個窗口

new Thread(mt,”a”).start();

new Thread(mt,”b”).start();

new Thread(mt,”c”).start();

}

 

}

 

全國這么多售票窗口就會出現以下結果:

圖示1:

 

我們可以看到a號窗口和和c號窗口都賣出了7號票,并且a號和c號窗口分別賣出了0號和-1號票。造成這種情況的原因是1、a線程和b線程在ticket=7的時候,a線程取出7號票以后,ticket還沒來的及減1b線程就取出了ticket此時ticket還等于7;2、在ticket=1時,b線程取出了1號票,ticket還沒來的及減1,a、c線程就先后進入了if判斷語句,這時ticket減1了,那么當a、c線程取票的時候就取到了0號和-1號票。( 前一段報的網上有一樣的火車票,一種是鎖沒有控制好,多線程引發問題,另一個原因就是有假票吧)

 

如何解決死鎖?

出現了上述情況怎樣改變呢,我們可以這樣做:當一個線程要使用火車票這個資源時,我們就交給它一把鎖,等它把事情做完后在把鎖給另一個要用這個資源的線程。這樣就不會出現上述情況。 實現這個鎖的功能就需要用到(java中)synchronized這個關鍵字。

 

synchronized這個關鍵字有兩種用法1、放方法名前形成同步方法;2、放在塊前構成同步塊。

 

package com.dr.runnable2;

class TicketSouce implements Runnable

{

//票的總數

private int ticket=10;

public void run()

{

for(int i=1;i<50;i++)

{

try {

//休眠1s秒中,為了使效果更明顯,否則可能出不了效果

Thread.sleep(1000);

} catch (InterruptedException e) {

e.printStackTrace();

}

this.sale();

}

}

public synchronized void sale()

{

if(ticket>0)

{

System.out.println(Thread.currentThread().getName()+”號窗口賣出”+this.ticket–+”號票”);

}

}

}

public class Test {

public static void main(String args[])

{

TicketSouce mt=new TicketSouce();

//基于火車票創建三個窗口

new Thread(mt,”a”).start();

new Thread(mt,”b”).start();

new Thread(mt,”c”).start();

}

 

}

 

 

圖片2:

 

 

c#當中:同步鎖實例

 

Public NotInheritable Class Singleton

Shared m_instance As Singleton = Nothing

Shared ReadOnly padlock As New Object()

 

Private Sub New()

End Sub

 

Public Shared ReadOnly Property Instance() As Singleton

Get

SyncLock? padlock

If m_instance Is Nothing Then

m_instance = New Singleton()

End If

Return m_instance

End SyncLock

End Get

End Property

End Class

 

同步鎖是一個線程先做,其他等待第一個釋放后再接著做,就不會發生死鎖的現象。

另一個小實例: A,B線程,同步資源C,D ,A線程鎖定一個C資源并試圖訪問D資源,B線程鎖定一個D資源并試圖訪問C資源,兩個相互等待就造成了死鎖,如同考試系統中的抽不出題,沒有任何反應。

 

總結

引起多線程問題的原因很多(靜態成員變量的慎用),如果在類成員函數中使用了私有的靜態成員變量,則該變量會在類的多個實例間共享,而不僅僅是一個實例內共享,但是在同一個時刻它只有一份,當多線程執行時,它會產生微妙的變化,線程之間的取傳值都造成了影響,這樣就造成了多線程的死鎖,產生一些自己不可預知的錯誤,強大的數據量測試可以測試出很多的問題。多線程高并發的問題值得我們以后考慮要深刻。

 

Comments are closed.