1.方法內的變數為執行緒安全
"非執行緒安全"問題存在於"例項變數"中,如果是方法內部的私有變數,則不存在"非執行緒安全"問題,所得結果也就是"執行緒安全"了。下面我們來編寫乙個"執行緒安全"的例子:
1.1 hasselfprivate類如下:
package edu.ymm.about_thread;1.2 建立乙個threada類:public class hasselfprivate else
system.out.println(username + "num = " + num);
} catch (interruptedexception e)
}}
package edu.ymm.about_thread;1.3 建立乙個threadb類:public class threada extends thread
@override
public void run()
}
package edu.ymm.about_thread;1.4 來測試一下這個例子:public class threadb extends thread
@override
public void run()
}
package edu.ymm.about_thread;執行結果如下:public class test
}
可見,方法中的變數不存在非執行緒安全問題,永遠是執行緒安全的。原因就是方法內部的變數是私有的。
2.例項變數非執行緒安全
(1):"非執行緒安全"其實會在多個執行緒對同乙個物件中的例項變數進行併發訪問時發生,產生的後果就是「髒讀」,也就是取到的資料其實是被更改過的。而「執行緒安全」就是以獲得的例項變數的值是經過同步處理的,不會出現髒讀的現象。
(2):用執行緒訪問的物件中如果有多個例項變數,則執行的結果有可能出現交叉情況。
(3):如果物件僅有1個例項變數,則可能出現覆蓋的情況。
下面舉乙個例子:
2.1 hasselfprivate類如下:
package edu.ymm.about_thread1;2.2 建立乙個threada類:public class hasselfprivate else
system.out.println(username + "num = " + num);
} catch (interruptedexception e)
}}
package edu.ymm.about_thread1;2.3建立乙個threadb類:public class threada extends thread
@override
public void run()
}
package edu.ymm.about_thread1;2.4來測試一下這個例子:public class threadb extends thread
@override
public void run()
}
package edu.ymm.about_thread1;結果如下:public class test
}
上述就是所謂的「非執行緒安全」的乙個例子。a的值不是我們預期的100了。要解決這種現象,只需要在a和b共同訪問的方法前加上「synchronized」就可以了。
更新這個類後:
package edu.ymm.about_thread1;再執行結果為:public class hasselfprivate else
system.out.println(username + " num=" + num);
} catch (interruptedexception e)
}}
所以,在兩個執行緒訪問同乙個物件中的同步方法(synchronized)時一定是執行緒安全的。
3.多個物件多個鎖
我們來改動一點:將測試中產生兩個例項物件。
3.1 hasselfprivate類如下:
package edu.ymm.about_thread2;上面**中有同步方方法add1,說明此方法應該被順序呼叫。public class hasselfprivate else
system.out.println(username + " num=" + num);
} catch (interruptedexception e)
}}
3.2 建立乙個threada類:
package edu.ymm.about_thread2;3.3建立乙個threadb類:public class threada extends thread
@override
public void run()
}
package edu.ymm.about_thread2;3.4來測試一下這個例子:public class threadb extends thread
@override
public void run()
}
package edu.ymm.about_thread2;執行結果如下:public class test
}
上述示例是兩個執行緒分別訪問乙個類的兩個不同例項的相同名稱的同步方法,效果卻是非同步的方式執行的。本示例由於建立了2個業務物件,在系統中產生了兩個鎖,所以執行結果是非同步的,列印的效果就是先列印b再列印a。
關鍵字synchronized取得的鎖都是物件鎖,而不是把一段**或方法(函式)當作鎖,所以在上面的示例中,哪個執行緒先執行帶synchronized關鍵字的方法,哪個執行緒就持有該方法所屬物件的鎖lock,那麼其他執行緒只能呈等待狀態,前提是多個執行緒訪問的是同乙個物件。
但是如果多個執行緒訪問多個物件,則jvm會建立多個鎖。
執行緒同步synchronized
synchronized只是保證在同乙個時刻,其他執行緒不能訪問鎖定的資源,但是其他方法或者是變數不能鎖定控制的 synchronized obj 上面語法格式中synchronized後括號裡的obj就是同步監視器,上面 的含義是 執行緒開始執行同步 塊之前,必須先獲得對同步監視器的鎖定。任何時刻...
synchronized同步方法
關鍵字synchronized 如果是在方法內的變數,則無所謂的的變數同步問題。因為在方法內部的變數都是私有的。synchronized如果是加在方法上面,則是對該物件的例項進行同步。如果有兩個執行緒同時對該方法進行操作,則會同步進行。對個例項多個執行緒,不存在同步的問題,那時jvm會生成多個鎖,應...
Synchronized同步方法
非執行緒安全 其實會在多個執行緒對同乙個物件中的例項變數進行併發訪問時發生,產生的後果就是 髒讀 也就是取到的資料其實是被更改過的。1 方法內的變數為執行緒安全的 方法內部的私有變數,則不存在 非執行緒安全 的問題,所得結果也就是 執行緒安全 的。2 例項變數非執行緒安全 如果多個執行緒共同訪問乙個...