很多人都知道,在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());
}
}