zoukankan      html  css  js  c++  java
  • 架构师养成记--4.volatile关键字

    volatile修饰的变量可在多个线程间可见。

    如下代码,在子线程运行期间主线程修改属性值并不对子线程产生影响,原因是子线程有自己独立的内存空间,其中有主内存中的变量副本。

     1 public class RunThread extends Thread{
     2 
     3     private volatile boolean isRunning = true;
     4     private void setRunning(boolean isRunning){
     5         this.isRunning = isRunning;
     6     }
     7     
     8     public void run(){
     9         System.out.println("进入run方法..");
    10         int i = 0;
    11         while(isRunning == true){
    12             //..
    13         }
    14         System.out.println("线程停止");
    15     }
    16     
    17     public static void main(String[] args) throws InterruptedException {
    18         RunThread rt = new RunThread();
    19         rt.start();
    20         Thread.sleep(1000);
    21         rt.setRunning(false);
    22         System.out.println("isRunning的值已经被设置了false");
    23     }
    24     
    25     
    26 }
    View Code

    那么如何达到预期效果让子线程停止呢?那就是变量isRunning使用volatile修饰,原理如下图

     

     需要注意的一点是,volatile关键字修饰的变量只有可见性,没有原子性。如下代码,如果使用第九行代码的话最终打印结果不是10000

     1 import java.util.concurrent.atomic.AtomicInteger;
     2 
     3 /**
     4  * volatile关键字不具备synchronized关键字的原子性(同步)
     5  * @author alienware
     6  *
     7  */
     8 public class VolatileNoAtomic extends Thread{
     9     //private static volatile int count;
    10     private static AtomicInteger count = new AtomicInteger(0);
    11     private static void addCount(){
    12         for (int i = 0; i < 1000; i++) {
    13             //count++ ;
    14             count.incrementAndGet();
    15         }
    16         System.out.println(count);
    17     }
    18     
    19     public void run(){
    20         addCount();
    21     }
    22     
    23     public static void main(String[] args) {
    24         
    25         VolatileNoAtomic[] arr = new VolatileNoAtomic[100];
    26         for (int i = 0; i < 10; i++) {
    27             arr[i] = new VolatileNoAtomic();
    28         }
    29         
    30         for (int i = 0; i < 10; i++) {
    31             arr[i].start();
    32         }
    33     }
    34     
    35     
    36     
    37     
    38 }
    View Code

    那么如何才能有原子性呢?可以对对象进行AtimicInteger  修饰

    多个addAndGet在一个方法内是非原子性的,需要加synchronized进行修饰,保证4个addAndGet整体原子性

     1 import java.util.ArrayList;
     2 import java.util.List;
     3 import java.util.concurrent.atomic.AtomicInteger;
     4 
     5 public class AtomicUse {
     6 
     7     private static AtomicInteger count = new AtomicInteger(0);
     8     
     9     //多个addAndGet在一个方法内是非原子性的,需要加synchronized进行修饰,保证4个addAndGet整体原子性
    10     /**synchronized*/
    11     public synchronized int multiAdd(){
    12             try {
    13                 Thread.sleep(100);
    14             } catch (InterruptedException e) {
    15                 e.printStackTrace();
    16             }
    17             count.addAndGet(1);
    18             count.addAndGet(2);
    19             count.addAndGet(3);
    20             count.addAndGet(4); //+10
    21             return count.get();
    22     }
    23     
    24     
    25     public static void main(String[] args) {
    26         
    27         final AtomicUse au = new AtomicUse();
    28 
    29         List<Thread> ts = new ArrayList<Thread>();
    30         for (int i = 0; i < 100; i++) {
    31             ts.add(new Thread(new Runnable() {
    32                 @Override
    33                 public void run() {
    34                     System.out.println(au.multiAdd());
    35                 }
    36             }));
    37         }
    38 
    39         for(Thread t : ts){
    40             t.start();
    41         }
    42 
    43 
    44     
    45         
    46 
    47         
    48     }
    49 }
    View Code
  • 相关阅读:
    NanoProfiler
    NanoProfiler
    Open Source Cassandra Gitbook for Developer
    Android Fragment使用(四) Toolbar使用及Fragment中的Toolbar处理
    Android Fragment使用(三) Activity, Fragment, WebView的状态保存和恢复
    Android Fragment使用(二) 嵌套Fragments (Nested Fragments) 的使用及常见错误
    Android Fragment使用(一) 基础篇 温故知新
    Set up Github Pages with Hexo, migrating from Jekyll
    EventBus源码解析 源码阅读记录
    Android M Permission 运行时权限 学习笔记
  • 原文地址:https://www.cnblogs.com/sigm/p/6132416.html
Copyright © 2011-2022 走看看