赞
踩
1、
/** * volatile 关键字,使一个变量在多个线程间可见 * mian,t1线程都用到一个变量,java默认是T1线程中保留一份副本,这样如果main线程修改了该变量, * t1线程未必知道 * * 使用volatile关键字,会让所有线程都会读到变量的修改值 * * 在下面的代码中,running是存在于堆内存的t对象中 * 当线程t1开始运行的时候,会把running值从内存中读到t1线程的工作区,在运行过程中直接使用这个副本, * 并不会每次都去读取堆内存,这样,当主线程修改running的值之后,t1线程感知不到,所以不会停止运行 * * */ @Slf4j(topic = "test") public class Demo { boolean running = true; List<String> list = new ArrayList<>(); /** * t1线程 */ public void test(){ log.debug("test start..."); boolean flag =running; while (running){ } log.debug("test end..."); } public static void main(String[] args) { Demo demo = new Demo(); new Thread(demo :: test,"t1").start(); try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } demo.running = false; } }
代码执行结果
线程会一直 执行并不会停止,可见 demo.running = false; 并没有通知到子线程中
2、
/** * 比如说第一个线程加到100了,还没往上加,另外一个线程来了,把100拿过来执行方法, * 然后第一个线程继续加到101,第二个线程也加到101,他两往回写都是101,线程不会管你加到哪儿了, * 虽然说加了2但是实际上只加了1. * volatile并不能保证多个线程共同修改running变量时所带来的不一致问题, * 也就是说volatile不能替代synchronized或者说volatile保证不了原子性 */ @Slf4j(topic = "test") public class Demo { volatile int count = 0; public void test(){ for (int i = 0; i < 10000; i++) { count ++; } } public static void main(String[] args) { Demo demo = new Demo(); List<Thread> threads = new ArrayList(); //new 10個线程 for (int i = 0; i < 10; i++) { threads.add(new Thread(demo::test, "t-" + i)); } //遍历这个10个线程 依次启动 threads.forEach((o)->o.start()); //等待10个线程执行完 threads.forEach((o)->{ try { o.join(); } catch (Exception e) { e.printStackTrace(); } }); log.debug(demo.count+""); } }
执行结果如下
17:39:48.478 [main] DEBUG test - 47677
可见volatile不能替代synchronized或者说volatile保证不了原子性
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。