Java多线程之volatile关键字

volatile关键字

1 1 import java.util.concurrent.TimeUnit; 2 2 3 3 /** 4 4 * volatile 5 5 * volatile 比 synchronized 效率高很多 6 6 * 能用volatile就不要用synchronized,很多并发容器都用了volatile 7 7 * volatile并不能保证多个线程共同修改running变量时所带来的不一致问题,也就是说volatile不能替代synchronized 8 8 */ 9 9 public class VolatileTest { 1010 1111 /*volatile*/ boolean running = true; 1212 //对比有无volatile的情况下,执行情况。 1313 1414 void m() { 1515 System.out.println(Thread.currentThread().getName() + " m start ..."); 1616 while (running) { 1717 try { 1818 TimeUnit.SECONDS.sleep(1); //没加volatile,加了休眠,有可能会让线程通信一下。 1919 } catch (InterruptedException e) { 2020 e.printStackTrace(); 2121 } 2222 System.out.println(Thread.currentThread().getName() + " while ..."); 2323 } 2424 System.out.println(Thread.currentThread().getName() + " m end ..."); 2525 } 2626 2727 public static void main(String[] args) { 2828 VolatileTest test = new VolatileTest(); 2929 new Thread(() -> { 3030 test.m(); 3131 }, "线程1").start(); 3232 //new Thread(test :: m, "线程1").start(); //这种写法更简洁 3333 3434 try { 3535 TimeUnit.SECONDS.sleep(2); 3636 } catch (InterruptedException e) { 3737 e.printStackTrace(); 3838 } 3939 4040 test.running = false; //改变running的值,停止死循环 4141 4242 //每个线程都有自己的一块内存区域,线程1拿到running这个值,会去运算,挡住内存running的值发生变化, 4343 // 就没空去主内存读取值, 4444 //当加了volatile这个值,主内存running这个值发生变化时,会通知线程1(缓存过期通知)这个running值发生了变化,再去读一次。 4545 } 4646 4747 } 48 49 1 import java.util.ArrayList; 50 2 import java.util.List; 51 3 52 4 /** 53 5 * volatile并不能保证多个线程共同修改running变量时所带来的不一致问题,也就是说volatile不能替代synchronized 54 6 * 55 7 * synchronized保障原子性和可见性 56 8 */ 57 9 public class VolatileTest1 { 5810 5911 volatile int count = 0; //光可见性是没用的,并不保证原子性 6012 6113 //还是需要加synchronized关键字 6214 void add() { 6315 for(int i=0; i<1000; i++) { 6416 count++; 6517 } 6618 } 6719 6820 public static void main(String[] args) { 6921 7022 VolatileTest1 test = new VolatileTest1(); 7123 List<Thread> threads = new ArrayList<>(10); 7224 //添加线程 7325 for (int i=0; i<10; i++) { 7426 threads.add(new Thread(test :: add, "线程" + i)); 7527 } 7628 //唤醒线程 7729 threads.forEach(t -> t.start()); 7830 7931 threads.forEach(t -> { 8032 try { 8133 t.join(); //主线程等待子线程完成在执行 8234 } catch (InterruptedException e) { 8335 e.printStackTrace(); 8436 } 8537 }); 8638 8739 System.out.println(test.count); 8840 } 8941 9042 }
点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

MySQL部分从库上面因为大量的临时表tmp_table造成慢查询

背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_

皕杰报表之UUID

​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

Opencv中Mat矩阵相乘——点乘、dot、mul运算详解

Opencv中Mat矩阵相乘——点乘、dot、mul运算详解2016年09月02日00:00:36 \牧野(https://www.oschina.net/action/GoToLink?urlhttps%3A%2F%2Fme.csdn.net%2Fdcrmg) 阅读数:59593