zoukankan      html  css  js  c++  java
  • Java多线程之volatile关键字

    volatile关键字

     1 import java.util.concurrent.TimeUnit;
     2 
     3 /**
     4  * volatile
     5  * volatile 比 synchronized 效率高很多
     6  * 能用volatile就不要用synchronized,很多并发容器都用了volatile
     7  * volatile并不能保证多个线程共同修改running变量时所带来的不一致问题,也就是说volatile不能替代synchronized
     8  */
     9 public class VolatileTest {
    10 
    11     /*volatile*/ boolean running = true;
    12     //对比有无volatile的情况下,执行情况。
    13 
    14     void m() {
    15         System.out.println(Thread.currentThread().getName() + " m start ...");
    16         while (running) {
    17             try {
    18                 TimeUnit.SECONDS.sleep(1); //没加volatile,加了休眠,有可能会让线程通信一下。
    19             } catch (InterruptedException e) {
    20                 e.printStackTrace();
    21             }
    22             System.out.println(Thread.currentThread().getName() + " while ...");
    23         }
    24         System.out.println(Thread.currentThread().getName() + " m end ...");
    25     }
    26 
    27     public static void main(String[] args) {
    28         VolatileTest test = new VolatileTest();
    29         new Thread(() -> {
    30             test.m();
    31         }, "线程1").start();
    32         //new Thread(test :: m, "线程1").start(); //这种写法更简洁
    33 
    34         try {
    35             TimeUnit.SECONDS.sleep(2);
    36         } catch (InterruptedException e) {
    37             e.printStackTrace();
    38         }
    39 
    40         test.running = false; //改变running的值,停止死循环
    41 
    42         //每个线程都有自己的一块内存区域,线程1拿到running这个值,会去运算,挡住内存running的值发生变化,
    43         // 就没空去主内存读取值,
    44         //当加了volatile这个值,主内存running这个值发生变化时,会通知线程1(缓存过期通知)这个running值发生了变化,再去读一次。
    45     }
    46 
    47 }
     1 import java.util.ArrayList;
     2 import java.util.List;
     3 
     4 /**
     5  * volatile并不能保证多个线程共同修改running变量时所带来的不一致问题,也就是说volatile不能替代synchronized
     6  *
     7  * synchronized保障原子性和可见性
     8  */
     9 public class VolatileTest1 {
    10 
    11     volatile int count = 0; //光可见性是没用的,并不保证原子性
    12 
    13     //还是需要加synchronized关键字
    14      void add() {
    15         for(int i=0; i<1000; i++) {
    16             count++;
    17         }
    18     }
    19 
    20     public static void main(String[] args) {
    21 
    22         VolatileTest1 test = new VolatileTest1();
    23         List<Thread> threads = new ArrayList<>(10);
    24         //添加线程
    25         for (int i=0; i<10; i++) {
    26             threads.add(new Thread(test :: add, "线程" + i));
    27         }
    28         //唤醒线程
    29         threads.forEach(t -> t.start());
    30 
    31         threads.forEach(t -> {
    32             try {
    33                 t.join(); //主线程等待子线程完成在执行
    34             } catch (InterruptedException e) {
    35                 e.printStackTrace();
    36             }
    37         });
    38 
    39         System.out.println(test.count);
    40     }
    41 
    42 }
  • 相关阅读:
    Django数据库查询优化-事务-图书管理系统的搭建
    模型层字段-多表查询-神奇的双下划线查询-F,Q查询
    Django的View(视图)-settings源码的解析-模板层-模板语法
    Django路由层与视图层
    Django框架的前奏(安装及介绍)
    面向对象的三大特性
    一,类的初识
    一,对象初识
    装饰器
    闭包
  • 原文地址:https://www.cnblogs.com/mxh-java/p/12246629.html
Copyright © 2011-2022 走看看