java 工作内存 主存_关于JMM中工作内存究竟什么时候同步到主存或者从主存中同步?...

先读取再设值:

new Thread(() -> {

int loop = 0;

while (run) {

loop++;

}

System.out.println("loop=" + loop);

}).start();

new Thread(()->{

sleep(1000);//先暂停1s确保先读取

run = false;

sleep(2000);

}).start();

测试结果:一直循环

先设值再读取:

new Thread(() -> {

int loop = 0;

sleep(1000);//先暂停1s确保先设值

while (run) {

loop++;

}

System.out.println("loop=" + loop);

}).start();

new Thread(()->{

run = false;

sleep(2000);

}).start();

测试结果:总是输出loop=0,说明根本没进循环,并且线程1先退出,过大概2s后线程2退出。

在测试1的基础上在循环中加入sleep(1):

new Thread(() -> {

int loop = 0;

while (run) {

loop++;

sleep(1);//在循环中让cpu执行1ms

}

System.out.println("loop=" + loop);

}).start();

new Thread(()->{

sleep(1000);//先暂停1s确保先读取

run = false;

sleep(2000);

}).start();

测试结果:输出loop=987,loop的次数在950-1050之间,说明在thread2的sleep(1000)之后thread1马上就读取到了最新值,而不是thread2线程结束后。如果sleep(2000),则总是输出loop=1,说明sleep方法结束后立马读取到正确的run值。

注意: 如果sleep函数里面的循环次数变少,还是不能退出循环。本机测试如果sleep函数中的循环次数小于29000次,则还是会一直循环下去,只要超过30000次,总是能退出循环。

在测试3的基础上,把sleep(1)替换为实际的for循环:

new Thread(() -> {

int loop = 0;

while (run) {

loop++;

//停顿1ms

for (long i = 0; i < 3000000L * 1; i++) {}

}

System.out.println("loop=" + loop);

}).start();

new Thread(()->{

sleep(1000);//先暂停1s确保先读取

run = false;

sleep(2000);

}).start();

测试结果:一直循环。不管 i 是多少都会一直循环。

在测试1的基础上加入synchronized语句:

new Thread(() -> {

int loop = 0;

while (run) {

loop++;

synchronized (Object.class){}

}

System.out.println("loop=" + loop);

}).start();

new Thread(()->{

sleep(1000);//先暂停1s确保先读取

run = false;

sleep(2000);

}).start();

测试结果:loop=45830307,能结束循环,loop次数没有意义。

在测试1的基础上加入lock.lock()语句:

new Thread(() -> {

int loop = 0;

while (run) {

loop++;

lock.lock(); //static Lock lock = new ReentrantLock();

}

System.out.println("loop=" + loop);

}).start();

new Thread(()->{

sleep(1000);//先暂停1s确保先读取

run = false;

sleep(2000);

}).start();

测试结果:loop=55020323,能正常退出循环。


版权声明:本文为weixin_29434351原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。