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

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

 public class RunThread extends Thread{

     private volatile boolean isRunning = true;
private void setRunning(boolean isRunning){
this.isRunning = isRunning;
} public void run(){
System.out.println("进入run方法..");
int i = 0;
while(isRunning == true){
//..
}
System.out.println("线程停止");
} public static void main(String[] args) throws InterruptedException {
RunThread rt = new RunThread();
rt.start();
Thread.sleep(1000);
rt.setRunning(false);
System.out.println("isRunning的值已经被设置了false");
} }

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

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

 import java.util.concurrent.atomic.AtomicInteger;

 /**
* volatile关键字不具备synchronized关键字的原子性(同步)
* @author alienware
*
*/
public class VolatileNoAtomic extends Thread{
//private static volatile int count;
private static AtomicInteger count = new AtomicInteger(0);
private static void addCount(){
for (int i = 0; i < 1000; i++) {
//count++ ;
count.incrementAndGet();
}
System.out.println(count);
} public void run(){
addCount();
} public static void main(String[] args) { VolatileNoAtomic[] arr = new VolatileNoAtomic[100];
for (int i = 0; i < 10; i++) {
arr[i] = new VolatileNoAtomic();
} for (int i = 0; i < 10; i++) {
arr[i].start();
}
} }

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

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

 import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger; public class AtomicUse { private static AtomicInteger count = new AtomicInteger(0); //多个addAndGet在一个方法内是非原子性的,需要加synchronized进行修饰,保证4个addAndGet整体原子性
/**synchronized*/
public synchronized int multiAdd(){
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
count.addAndGet(1);
count.addAndGet(2);
count.addAndGet(3);
count.addAndGet(4); //+10
return count.get();
} public static void main(String[] args) { final AtomicUse au = new AtomicUse(); List<Thread> ts = new ArrayList<Thread>();
for (int i = 0; i < 100; i++) {
ts.add(new Thread(new Runnable() {
@Override
public void run() {
System.out.println(au.multiAdd());
}
}));
} for(Thread t : ts){
t.start();
} }
}

架构师养成记--4.volatile关键字的更多相关文章

  1. 架构师养成记--3.synchronized细节问题

    一.synchronized有锁重入的特点,某个线程得到对象的锁后,再次请求此对象可以再次得到改对象的锁.如下示例,在method1中调用method2,在method2中调用method3,而met ...

  2. 架构师养成记--35.redis集群搭建

    前记:redis哨兵经验之谈.哨兵做主从切换可能要花费一两秒,这一两秒可能会丢失很多数据.解决方法之一是在java代码中做控制,try catch 到 链接断开的异常就sleep 一两秒钟再conti ...

  3. 架构师养成记--15.Disruptor并发框架

    一.概述 disruptor对于处理并发任务很擅长,曾有人测过,一个线程里1s内可以处理六百万个订单,性能相当感人. 这个框架的结构大概是:数据生产端 --> 缓存 --> 消费端 缓存中 ...

  4. 架构师养成记--14.重入锁ReentrantLock 和 读写锁 ReentrantReadWriteLock

    ReentrantLock 有嗅探锁定和多路分支等功能,其实就是synchronized,wait,notify的升级. this锁定当前对象不方便,于是就有了用new Object()来作为锁的解决 ...

  5. 架构师养成记--12.Concurrent工具类CyclicBarrier和CountDownLatch

    java.util.concurrent.CyclicBarrier 一组线程共同等待,直到达到一个公共屏障点. 举个栗子,百米赛跑中,所有运动员都要等其他运动员都准备好后才能一起跑(假如没有发令员) ...

  6. 架构师养成记--11.Executor概述

    常用方法 Executors.newFiexdPool(int nThreads);固定线程数量的线程池: Executors.newSingleThreadExecutor();单个线程的线程池: ...

  7. 架构师养成记--10.master-worker模式

    master-worker模式是一种并行计算模式,分为master进程和worker进程两个部分,master是担任总管角色,worker才是执行具体任务的地方. 总体流程应该是这样的: 具体一点,代 ...

  8. 架构师养成记--9.future模式讲解

    什么是future模式呢?解释这个概念之前我们先来了解一个场景吧,财务系统的结账功能,这个功能可能是每个月用一次,在这一个月中相关的数据量已经积累得非常大,这一个功能需要调用好几个存储过程来完成.假如 ...

  9. 架构师养成记--8.Queue

    一.ConcurrentLinkedQueue 是一个适合在高并发场景下,无锁,无界的,先进先出原则.不允许为null值,add().offer()加入元素,这两个方法没区别:pull().peek( ...

随机推荐

  1. Tableview中Dynamic Prototypes动态表的使用

    Tableview时IOS中应用非常广泛的控件,当需要动态的添加多条不同的数据时,需要用动态表来实现,下面给出一个小例子,适用于不确定Section的数目,并且每个Section中的行数也不同的情况, ...

  2. mysql5.7.1 zip版本安装记录

    很久没遇到使用mysql的项目了,今天下载了个,发现变了很多,搜索了下,发现按http://www.cnblogs.com/wenthink/p/MySQLInstall.html中提到的基本可以使用 ...

  3. 关于IPB帧与恒定比特率、动态比特率的详解

    之所以写这篇文章是因为有朋友对IPB帧的设置比较感兴趣,回复中说得比较简单,因此在这里详细的写一下,虽然说一般情况下我们很少去设置这个IPB帧,不过,如果真的学好了,并且清楚的了解了这个IPB帧的概念 ...

  4. #ifndef _LED_H #endif啥意思?

    #ifndef _LED_H#ifndef _LED_H ...... ...... #endif 避免重复引用头文件的内容.

  5. Vsphere初试——基本安装

    现有工具: 一台Dell PowerEdge R820服务器 VMware-VMvisor-Installer-5.5.0.update01-1623387.x86_64(ESXi).iso VMwa ...

  6. Linux下5种IO模型的小结

    概述 接触网络编程,我们时常会与各种与IO相关的概念打交道:同步(Synchronous).异步(ASynchronous).阻塞(blocking)和非阻塞(non-blocking).关于概念的区 ...

  7. 基础SQL语句/语法

    SQL是现在进入互联网工作人们的必须技能之一,下面分享自己觉得很nice的SQL基本语句,从网上找了,觉得很不错,就分享给大家!简要介绍基础语句: 1.说明:创建数据库  Create DATABAS ...

  8. WPFTookit Chart 入门

    如何使用WPFToolKit Chart private void button1_Click(object sender, EventArgs e) { var s = new Series(); ...

  9. 网盘的选择,百度网盘、google drive 还是 Dropbox

    我是国内用户,需要越过Chinawall 我使用的是一枝红杏,用着还行 如果要买,结账时输入'laod80' 一枝红杏官网:官网地址 Dropbox: 稳定,速度快 Dropbox官网:链接 操作十分 ...

  10. java之多线程 一

    概述: 几乎任何的操作系统都支持运行多个任务,通常一个任务就是一个程序,而一个程序就是一个进程.当一个进程运行时,内部可能包括多个顺序执行流,每个顺序执行流就是一个线程. 进程与线程: 进程是指处于运 ...