很多人都知道,在Java多線程編程中,有一個重要的關鍵字,synchronized。但是很多人看到這個東西會感到困惑:“都說同步機制是通過對象鎖來實現的,但是這麼一個關鍵字,到底有什麼作用呢?”
synchronized定義在方法中,保證在多線程運行此方法的時候,可以保證方法的逐步執行,即:當有線程佔用此資源的時候,其他線程進行等待,當前一線程執行完,後一線程繼續執行,從而保證數據的正確性。
package com.ada;
/**
* @author fanyanyan
* @Title: VolatileDemo
* @ProjectName JavaProject
* @date 2019/5/21 9:02
*/
public class VolatileDemo {
/**
* volatile只有可見性,無法保證原子性
*/
private volatile int num = 0;
public int getNum() {
return this.num;
}
public synchronized void increase() {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (this.num % 2 == 0) {
this.num++;
} else {
this.num--;
}
// this.num++;
System.out.println("過程中 " + num);
}
public static void main(String[] args) {
final VolatileDemo volatileDemo = new VolatileDemo();
for (int i = 0; i < 500; i++) {
new Thread(new Runnable() {
@Override
public void run() {
volatileDemo.increase();
}
}).start();
System.out.println("=======" + i);
}
//如果還有子線程在執行,主線程讓出cpu資源,直到子線程執行完畢,主線程繼續執行
// System.out.println(Thread.activeCount());
while (Thread.activeCount() > 2) { // 大於2是因爲存在主線程和其守護線程
Thread.yield();
}
System.out.println("-------num:" + volatileDemo.getNum());
}
}
當方法中不使用synchronized時,當數據循環次數變多的情況下,數據的準確性就會降低。
package com.ada;
/**
* @author fanyanyan
* @Title: VolatileDemo
* @ProjectName JavaProject
* @date 2019/5/21 9:02
*/
public class VolatileDemo {
/**
* volatile只有可見性,無法保證原子性
*/
private volatile int num = 0;
public int getNum() {
return this.num;
}
// 不使用synchronized,但循環次數爲500次時,很可能會出錯
public void increase() {
try {
//休眠更容易重現結果不爲0的情況
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (this.num % 2 == 0) {
this.num++;
} else {
this.num--;
}
// this.num++;
System.out.println("過程中 " + num);
}
public static void main(String[] args) {
final VolatileDemo volatileDemo = new VolatileDemo();
for (int i = 0; i < 500; i++) {
new Thread(new Runnable() {
@Override
public void run() {
volatileDemo.increase();
}
}).start();
System.out.println("=======" + i);
}
//如果還有子線程在執行,主線程讓出cpu資源,直到子線程執行完畢,主線程繼續執行
// System.out.println(Thread.activeCount());
while (Thread.activeCount() > 2) {
Thread.yield();
}
System.out.println("-------num:" + volatileDemo.getNum());
}
}