/*
对于volatile修饰的变量,jvm虚拟机只是保证从 主内存 加载到 线程工作内存的值 是最新的《直接读取 主内存数据, 并写回到 主内存中。中间有可能不是原子操作》
例如假如线程1,线程2 在进行read,load 操作中,发现主内存中count的值都是5,那么都会加载这个最新的值
在线程1堆count进行修改之后,会write到主内存中,主内存中的count变量就会变为6
线程2由于已经进行read,load操作,在进行运算之后,也会更新主内存count的变量值为6
导致两个线程即使用volatile关键字修改之后,还是会存在并发的情况。
*/
//volatile告诉jvm, 它所修饰的变量不保留拷贝,直接访问主内存中的(也就是上面说的A)
//在Java内存模型中,有main memory,每个线程也有自己的memory (例如寄存器)。
//一个变量声明为volatile,就意味着这个变量是随时会被其他线程修改的,因此不能将它cache在线程memory中。
//因此volatile只是在线程内存和“主”内存间同步某个变量的值,而synchronized通过锁定和解锁某个监视器同步所有变量的值。
//显然synchronized要比volatile消耗更多资源。
//在使用volatile关键字时要慎重,并不是只要简单类型变量使用volatile修饰,对这个变量的所有操作都是原来操作,
//当变量的值由自身的上一个决定时,如n=n+1、n++ 等,volatile关键字将失效。
//只有当变量的值和自身上一个值无关时对该变量的操作才是原子级别的,如n = m + 1,这个就是原级别的。
public class NewThreadTest {
public static volatile int count = 0;//定义类变量
private static Object obj = new Object();
public static void inc() {
//这里延迟1毫秒,使得结果明显
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
//synchronized (this) {//***************** static donot exist "this" object....
synchronized(obj){
count++;
System.out.println("运行结果:Counter.count"+count);
}
}
public static void main(String[] args) {
//同时启动1000个线程,去进行i++计算,看看实际结果
for (int i = 0; i < 1000; i++) {
new Thread(new Runnable() {//匿名内部类调用静态方法
public void run() {
NewThreadTest.inc();
}
}).start();
}
}
}
用runnable的方法 进行实现
public class MyRunnable implements Runnable {
private int count = 100;
public synchronized void run() {
count--;
System.out.println("count===="+count);
}
}
public class MyTreadTest {
public static void main(String[] args) {
Runnable myrun = new MyRunnable();
for(int i=0;i<100;i++){
new Thread(myrun).start();
}
}
}