本人曰:剛學java、jsp不久,對static變量倒是有所理解,但是,對static方法理解不夠清楚,看完這篇文章,覺得還是講的蠻清晰的,所以轉載來備忘,也和大家一起分享學習之。
~~~~~~~~~~~~~以下轉載~~~~~~~~~~~~~~~~~~~~~~~~~~~
最近幾年用Java寫了一些多線程的程序,有一種需求,是建立一個公用的static類型Llit,類裏面寫了一些對於List的get、set、 update之類的方法,而有一個線程從數據庫中讀取數據並維護這個List,其它有幾百個幾千個線程讀取和修改這個List。
寫本文的目的,就是爲這種需求提出最佳解決方案:
一、首先了解一下同步安全問題:
對於線程安全,我們先看兩個例子:
class CheckoutLane
{
public static float GetTotal(Cart cart)
{
float total = 0;
for (int i = 0; i < cart.GroceryItems.Length; i++)
{
total += cart.GroceryItems[i].Price;
Thread.Sleep(100);
}
return total;
}
}
對於上面的代碼,你使用多少的線程來控制,都是安全的。因爲線程之間,不會共享什麼資源,唯一相同的是使用了同一個邏輯。其實這是在破壞線程的前題方面下功夫,出現線程不安全的條件都沒有了,那肯定就是線程安全的。
class CheckoutLane
{
static float total;
public static float GetTotal(Cart cart)
{
total = 0;
for (int i = 0; i < cart.GroceryItems.Length; i++)
{
total += cart.GroceryItems[i].Price;
Thread.Sleep(100);
}
return total;
}
}
對於上面的這個例子,不是線程安全的,因爲共享了static float total;這個資源,而各個線程都隨機都被調用,可以任意修改total這個數據。這個,就正如多個收銀員共享櫃檯,任意執行收銀操作一樣。
二、最簡單的解決辦法,加synchronized:
在加synchronized之前,首先要明白:
1、synchronized會影響代碼執行效率;
2、synchronized雖然加在一個方法上,但是影響的是整個類或類的實例;
3、兩個synchronized方法不能相互調用,否則會形成死鎖,很好理解,A調B,B調A,A和B相互等着對方結束,但是使用了synchronized,都不能結束,程序就死在那裏了。