背景:
今天同事在看我寫鎖同步的總結,興致來了想考考我,問我synchronized 保證變數的可見性嗎?
我回答可以,他的答案是synchronized不保證可見性,volatile才保證可見性,結果兩人起來爭執,為此他特意寫了如下代碼來證明他說的是正確的:
重點戲
/**
* 證明,synchronized能不能保重物件可見性,
*/
public class SynchronizedLock {
private static int count = 0;
public void incr() {
synchronized (this) {
count ++;
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) throws InterruptedException {
SynchronizedLock synchronizedLock = new SynchronizedLock();
for (int i = 0; i < 1000; i++) {
new Thread(synchronizedLock::incr).start();
}
Thread.sleep(1000);
System.out.println(count);
}
}
他執行了下,他說明了之前看視頻老師就是用這個實體,為什么有的時候,輸出是:
999
有的時候是:
998
有的時候是:
1000
看到上面的代碼,一開始我還真疑惑了一下,結果發現一個Thread.sleep(1000),這是個什么鬼,確定是最后兩個執行緒/一個執行緒在println的時候已經執行了?其實確定不了,我讓他把 Thread.sleep(1000); 改成 Thread.sleep(3000) ,看看列印的有998/999過嗎?結果肯定是沒出現過998/999,
當時就懟他的JMM基礎不扎實,就只是會被網上的答案,
結論
JMM需要解決的問題就是Java多執行緒通信的問題,多執行緒通信的問題主要是三個問題:有序性、可見性和原子性,synchronized屬于鎖,鎖也是需要解決通信的三個問題的,其中可見性是有鎖的記憶體原語保證的:
1)獲取鎖的記憶體語意:當執行緒獲取鎖的時候,JMM會把執行緒對于的本地記憶體置為無效,從而使得被監視器保護的臨界區代碼必須從主記憶體讀取共享變數,
2)釋放鎖的記憶體語意:當執行緒釋放鎖的時候,JMM會把該執行緒對應的本地記憶體中的共享變數重繪到記憶體中,
希望那個同事能看到這篇文章吧,他到現在都不理我了,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/205290.html
標籤:其他
上一篇:單例模式5種實作方式
