看一遍就懂,详解java多线程——volatile
多线程一直以来都是面试必考点,而volatile、synchronized也是必问点,这里我试图用容易理解的方式来解释一下volatile。
来看一下它的最大特点和作用:
一 使变量在多个线程间可见
public class OneThread extends Thread {
    private boolean running = true;
    @Override
    public void run() {
        System.out.println("进入run方法");
        while (running) {
        }
        System.out.println("线程执行完毕");
    }
    public void setRunning(boolean running) {
        this.running = running;
    }
}
测试类
public class Test {
    public static void main(String[] args) throws InterruptedException {
        OneThread oneThread = new OneThread();
        oneThread.start();
        Thread.sleep(1000);
        oneThread.setRunning(false);
    }
}
在OneThread类中有一个全局变量running,它会进到堆里,被所有线程共享。
public class Test {
    public static void main(String[] args) throws InterruptedException {
        OneThread oneThread = new OneThread();
        oneThread.start();
        Thread.sleep(1000);
        oneThread.setRunning(false);
        new Thread(() -> System.out.println(oneThread.isRunning())).start();
    }
}
这里我们再起一个线程去读取running的值,这时读取的就是主内存的值了。
public class OneThread extends Thread {
    private boolean running = true;
    @Override
    public void run() {
        System.out.println("进入run方法");
        try {
            Thread.sleep(1100);
            System.out.println(running);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("线程执行完毕");
    }
    public void setRunning(boolean running) {
        this.running = running;
    }
    public boolean isRunning() {
        return running;
    }
}
我们用volatile修饰running后,再试一下那个死循环代码,终于OK了。
二 volatile是非原子性的
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
public class VolatileTest {
    private static CyclicBarrier barrier = new CyclicBarrier(100);
    private static volatile int count;
    public static void main(String[] args) {
        MyThread[] mythreadArray = new MyThread[1000];
        for (int i = 0; i < 1000; i++) {
            mythreadArray[i] = new MyThread();
            mythreadArray[i].start();
        }
    }
    static class MyThread extends Thread {
        private void addCount() {
            for (int i = 0; i < 100; i++) {
                count++;
            }
            System.out.println("count=" + count);
        }
        @Override
        public void run() {
            try {
                barrier.await();
                addCount();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (BrokenBarrierException e) {
                e.printStackTrace();
            }
        }
    }
}
三 和Synchronize对比
看一遍就懂,详解java多线程——volatile的更多相关文章
- 异常处理器详解 Java多线程异常处理机制  多线程中篇(四)
		在Thread中有异常处理器相关的方法 在ThreadGroup中也有相关的异常处理方法 示例 未检查异常 对于未检查异常,将会直接宕掉,主线程则继续运行,程序会继续运行 在主线程中能不能捕获呢? 我 ... 
- 【Java学习笔记之三十四】超详解Java多线程基础
		前言 多线程并发编程是Java编程中重要的一块内容,也是面试重点覆盖区域,所以学好多线程并发编程对我们来说极其重要,下面跟我一起开启本次的学习之旅吧. 正文 线程与进程 1 线程:进程中负责程序执行的 ... 
- 【java】详解java多线程
		目录结构: contents structure [+] 线程的创建与启动 继承Thread类创建线程类 实现Runnable接口创建线程类 使用Callable和Future创建线程 线程的生命周期 ... 
- 详解Java多线程锁之synchronized
		synchronized是Java中解决并发问题的一种最常用的方法,也是最简单的一种方法. synchronized的四种使用方式 修饰代码块:被修饰的代码块称为同步语句块,其作用的范围是大括号{}括 ... 
- 详解Java多线程编程中LockSupport
		LockSupport是用来创建锁和其他同步类的基本线程阻塞原语. LockSupport中的park() 和 unpark() 的作用分别是阻塞线程和解除阻塞线程,而且park()和unpark() ... 
- 详解Java多线程编程中LockSupport类的线程阻塞用法
		LockSupport类是Java6(JSR166-JUC)引入的一个类,提供了基本的线程同步原语.LockSupport实际上是调用了Unsafe类里的函数,归结到Unsafe里,只有两个函数: p ... 
- 从缓存入门到并发编程三要素详解 Java中 volatile 、final 等关键字解析案例
		引入高速缓存概念 在计算机在执行程序时,以指令为单位来执行,每条指令都是在CPU中执行的,而执行指令过程中,势必涉及到数据的读取和写入. 由于程序运行过程中的临时数据是存放在主存(物理内存)当中的,这 ... 
- java基础(十五)----- Java 最全异常详解 ——Java高级开发必须懂的
		本文将详解java中的异常和异常处理机制 异常简介 什么是异常? 程序运行时,发生的不被期望的事件,它阻止了程序按照程序员的预期正常执行,这就是异常. Java异常的分类和类结构图 1.Java中的所 ... 
- 详解Java中的clone方法
		详解Java中的clone方法 参考:http://blog.csdn.net/zhangjg_blog/article/details/18369201/ 所谓的复制对象,首先要分配一个和源对象同样 ... 
随机推荐
- MR案例:路径过滤PathFilter
			问题描述:现有一批cookie日志,按照日期进行存放,如目录 “dir/2015-08-08” 下存放2015-08-08这一天的所有cookie.而目录 “/2015-08-08/” 下又根据数据文 ... 
- uboot的FIT功能
			1.FIT介绍 Flattend Image Tree 英文原版介绍: FIT is formally a FDT, which can include images of various types ... 
- SaltStack执行状态收集入库-第五篇
			实验目标 1.salt执行的状态然后结果写入MySQL可以方便查询执行salt执行的历史记录 实现方法 1.使用salt的return功能,是minion直接写入MySQL(相对比较麻烦) 2.使用m ... 
- 动态规划入门-01背包问题 - poj3624
			2017-08-12 18:50:13 writer:pprp 对于最基础的动态规划01背包问题,都花了我好长时间去理解: poj3624是一个最基本的01背包问题: 题意:给你N个物品,给你一个容量 ... 
- C# 同步调用、异步调用、异步回调
			本文将主要通过“同步调用”.“异步调用”.“异步回调”三个示例来讲解在用委托执行同一个“加法类”的时候的的区别和利弊. 首先,通过代码定义一个委托和下面三个示例将要调用的方法: public dele ... 
- HtmlAgilityPach基本使用方法
			//过滤html标签 static void InnerText() { HtmlWeb htmlWeb = new HtmlWeb(); HtmlDocument doc = htmlWeb.Loa ... 
- django学习错误笔记
			1.运行python manage.py makemigrations polls 出现错误 
- centos7 VNC安装
			root用户: yum install tigervnc-server .service vim /etc/systemd/system/vncserver@:.service .service vn ... 
- 委托---.net4.0提供两个比较重要的委托
			public delegate void Action<[in T1][,in T2][,in T3]......>([T1 t1][,T2 t2][,T3 t3]...) public ... 
- Ansible 小手册系列 三(命令介绍)
			仅仅只是介绍,可以选择跳过 ansible ansible是指令核心部分,其主要用于执行ad-hoc命令,即单条命令.默认后面需要跟主机和选项部分,默认不指定模块时,使用的是command模块. Us ... 
