• 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 }
  • 相关阅读:
    Ajax技术的工作原理
    《统计学习方法》第七章,支持向量机
    《西瓜书》第四章,决策树3
    OpenCL 矩阵乘法
    MPI 集合通信函数 MPI_Reduce(),MPI_Allreduce(),MPI_Bcast(),MPI_Scatter(),MPI_Gather(),MPI_Allgather(),MPI_Scan(),MPI_Reduce_Scatter()
    有关CUBLAS中的矩阵乘法函数
    TensorFlow 笔记04
    TensorFlow 笔记03-TensoeFlow 和 TensorRT 调试的一些方法
    TensorFlow 笔记02-mnist 的 tensorRT 实现,从 .npz 文件中加载参数进行推理
    TensorFlow 笔记01-mnist 的两种 tensorFlow 实现,保存和加载模型的三种方法
  • 原文地址:https://www.cnblogs.com/mxh-java/p/12246629.html
Copyright © 2020-2023  润新知