多執行緒中使用靜態方法存線上程安全的問題
我們知道,靜態欄位和靜態方法的呼叫都是通過類來呼叫的,靜態方法不會對特定的例項操作,只能呼叫呼叫類中的其他屬性和靜態方法,不能呼叫類中的非靜態屬性和非靜態方法。例項方法可以對特定的例項操作,既能訪問靜態屬性和靜態方法,也能訪問例項屬性和例項方法。
在多執行緒中使用靜態方法是否有安全問題?這樣看在靜態方法中時候使用了靜態成員。在多執行緒中使用一個靜態方法的時候,每個執行緒共享一個靜態欄位,如果該靜態方法不去操作一個靜態變數,只在方法內部使用區域性變數,則不會造成安全性問題。但是,如果該靜態方法操作了一個靜態欄位,則需要在靜態方法中採用互斥訪問的方式來對其進行安全處理。
先來看沒有執行緒安全問題的例項:
public class Test
{
public static String hello(String str)
{
String tmp = "";
tmp = tmp + str;
return tmp;
}
}
上述示例中是執行緒安全的,這是因為在靜態方法中聲明瞭區域性變數,每個執行緒在呼叫的時候,都會建立一份新的區域性變數,比如這裡的tmp,而不會共享一個儲存單元。
以下是執行緒不安全的:
這是因為在靜態方法中又返回了靜態變數,對於靜態變數來說,類在載入的時候會佔用同一個儲存區,而每個執行緒都是公用這個儲存區的,因此存線上程安全的問題。public class Test { Private static Test test public static Test hello() { If(tets==null) Test=new Test(); return test; } }
因此在設計工具類的時候,對於沒有使用到靜態變數的靜態工具類方法,是不需要加鎖的(synchronized)。
在使用單例模式做工具類的時候,這個時候靜態方法需要被加鎖,這是因為所有的執行緒雖然有自己的方法棧,但是在方法棧中操作的是同一個物件的實體,所以需要進行加鎖同步,來實現每個執行緒都需要等待鎖的釋放才能使用該物件的引用。
但是在多例模式做工具類的時候,是不需要加鎖的,因為每個執行緒中有自己的方法棧,但是在方法棧中建立了獨立的物件引用,可以看成是執行緒都是在自己的方法棧中操作區域性的物件引用,因此這個時候不需要同步。