文档章节

多线程学习笔记(十二)

scymore
 scymore
发布于 2016/09/13 17:19
字数 1012
阅读 47
收藏 1

volatile的作用是使变量在多个线程间可见

1.死循环

public class PrintInfo implements Runnable {

    private boolean statu = true;

    public boolean isStatu() {
        return statu;
    }

    public void setStatu(boolean statu) {
        this.statu = statu;
    }

    public void printInfo() {
        try {
            while(statu  == true){
                System.out.println("The Thread Name Is " + Thread.currentThread().getName());
                Thread.sleep(1000);
                Thread.sleep(1000);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void run() {
        printInfo();
    }
}
public class Run {
    public static void main(String[] args){
PrintInfo printInfo = new PrintInfo();
printInfo.printInfo();
System.out.println("Try To Stop The Thread");
printInfo.setStatu(false);

}
}

运行结果:

 

2.解决同步死循环

将一中的代码Run类修改为

public class Run {
    public static void main(String[] args) throws InterruptedException {
        PrintInfo printInfo = new PrintInfo();
        Thread thread = new Thread(printInfo);
        thread.start();
        Thread.sleep(1000);
        System.out.println("Try To Stop The Thread");
        printInfo.setStatu(false);
    }
}

运行结果:

但当上面的实例代码运行在 -server服务器模式的64位的JVM上时,会出现死循环,解决的办法是使用volatile关键字.

volatile关键字的作用是强制从公共堆栈中取得变量的值,而不是从线程使用数据栈中取得变量的值

 

3.解决异步死循环

将1中的代码PrintInfo修改为

public class PrintInfo implements Runnable {

    volatile private boolean statu = true;

    public boolean isStatu() {
        return statu;
    }

    public void setStatu(boolean statu) {
        this.statu = statu;
    }

    public void printInfo() {
        try {
            while(statu  == true){
                System.out.println("The Thread Name Is " + Thread.currentThread().getName());
                Thread.sleep(1000);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void run() {
        printInfo();
    }
}

运行结果:

 

4.关键字synchronized与volatile的区别

使用volatile关键字增加了实例变量在多个线程之间的可见性,但是volatile关键字的缺点是不支持原子性.

    1).关键字volatile是线程同步的轻量级实现,所以volatile性能肯定比synchronized要好,并且volatile只能修饰于变量,二synchronized可以修饰方法,以及代码块.随着JDK新版本的发布,synchronized关键字的执行效率得到很大提升,在开发中使用synchronized关键字的比例还是比较大.

    2).多线程访问volatile不会发生阻塞,二synchronized回出现阻塞

    3).volatile能保证数据的可见性.但不能保证原子性,而synchronized可以保证原子性,也可以间接保证可见性,以内他会将使用内存和公共内存中的数据做同步.

    4).关键字volatile解决的是变量在多个线程之间的可见性,而synchronized关键字解决的是多个线程之间访问资源的同步性,

线程安全包含原子性和可见性两个方面,JAVA的同步机制都是围绕这两个方面来确保线程安全的.

 

5.volatile的非原子特性

public class VolatileThread extends Thread{

    volatile public static int count ;

    private static void sumCount(){
        for(int i = 0 ; i < 10 ; i ++){
            count ++;
        }
        System.out.println("count = " + count);
    }

    @Override
    public void run() {
        sumCount();
    }
}
public class Run {
    public static void main(String[] args){
        VolatileThread[] volatileThreads = new VolatileThread[100];
        for(int i = 0 ; i < 10 ; i ++){
            volatileThreads[i] = new VolatileThread();
        }
        for(int i = 0 ; i < 10 ; i ++){
            volatileThreads[i].start();
        }
    }
}

运行结果:

 

更改VolatileThread类代码为:

public class VolatileThread extends Thread{

    volatile public static int count ;

    synchronized private static void sumCount(){
        for(int i = 0 ; i < 10 ; i ++){
            count ++;
        }
        System.out.println("count = " + count);
    }

    @Override
    public void run() {
        sumCount();
    }
}

运行结果:

 

关键字volatile主要使用的场合是在多个线程中可以感知实例变量被更改了,并且可以获得最新的值使用,也就是用多线程读取共享变量时可以获取最新值使用.

关键字volatile提示线程每次从共享内存中读取变量,而不是从私有内存中读取,这样就保证了同步数据的可见性,但需要注意的是:如果修改实例变量中的数据,比如i++,这样的操作其实并不是一个院子操作,也就是非线程安全的.

表达式i++的操作不走分解如下:

    1).从内存中获取i的值,

    2).计算i的值,

    3).将计算后的值存储到内存中.

如果在第二步时,另一个线程也修改了i的值,那么这个时候就会出现脏数据,解决的办法就是使用synchronized关键字,所以volatile本身并不处理数据的原子性,而是强制对数据的读写及时影响到主内存.

© 著作权归作者所有

scymore

scymore

粉丝 6
博文 34
码字总数 22032
作品 0
成都
程序员
私信 提问

hjimce算法类博文目录 个人博客:http://blog.csdn.net/hjimce 个人qq:1393852684 知乎:https://www.zhihu.com/people/huang-jin-chi-28/activities 一、深度学习 深度学习(七十)darknet...

hjimce
2016/01/24
0
0
《Pro ASP.NET MVC 3 Framework》学习笔记目录

《Pro ASP.NET MVC 3 Framework》简介: 作者: Adam Freeman 和 Steven Sanderson 出版社: Apress; New 平装: 820页 语种: 英语 ISBN: 1430234040 声明:笔记里面按我自己的理解翻译了大部分...

mszhangxuefei
2012/02/07
0
0
“我爱智能”原创性博客索引

不知不觉,博客也写出了一点小体系,新的阶段已经开始,未来希望再接再厉继续补充这一体系,在成长中写博客,在博客中成长,在此先做一个小的梳理,谢谢大家的支持。 一)关于深度学习系列 ...

on2way
2015/08/29
0
0
Android实战经验之图像处理及特效处理的集锦(总结版)

1 Android学习笔记进阶之在图片上涂鸦(能清屏) 2 Android学习笔记之详细讲解画圆角图片 3 Android学习笔记进阶20之得到图片的缩略图 4 Android学习笔记进阶19之给图片加边框 5 Android学习笔...

xiaosi
2012/03/12
40.2K
25
MyBatis学习笔记系列教程

【MyBatis学习笔记】系列之预备篇一:ant的下载与安装 【MyBatis学习笔记】系列之预备篇二:ant入门示例 【MyBatis学习笔记】系列之一:MyBatis入门示例 【MyBatis学习笔记】系列之二:MyBat...

HenrySun
2016/10/15
153
0

没有更多内容

加载失败,请刷新页面

加载更多

Echars鼠标点击事件多次触发

本文转载于:专业的前端网站➭Echars鼠标点击事件多次触发 gChart.on('click', function (params) { if (params.componentSubType == "bar" && params.componentType == "serie......

前端老手
刚刚
0
0
springboot2.0.6(附) 解析META-INF/spring.factories通过系统加载类获取对应的 class 的全限定名称

在 SpringBoot中是通过getSpringFactoriesInstances(Class<T> type)方法获取所有classpath下面的META-INF/spring.factories文件,然后根据type值找到对应的 class 的全限定名称列表。下面我来...

小亮89
1分钟前
0
0
zk工厂方法实现NIOServerCnxnFactory

NIOServerCnxnFactory类 内部类 AbstractSelectThread AcceptThread SelectorThread 属性 ZOOKEEPER_NIO_SESSIONLESS_CNXN_TIMEOUT 10s session过期时间 ZOOKEEPER_NIO_NUM_SELECTOR_THREADS......

writeademo
5分钟前
0
0
天猫精灵业务如何使用机器学习PAI进行模型推理优化

作者:如切,悟双,楚哲,晓祥,旭林 引言 天猫精灵(TmallGenie)是阿里巴巴人工智能实验室(Alibaba A.I.Labs)于2017年7月5日发布的AI智能语音终端设备。天猫精灵目前是全球销量第三、中国...

阿里云官方博客
12分钟前
1
0
BJL技巧之大路馆擦法—《利辰逸》

很多朋友刚玩百佳时间不长,不知道如何看路,今 天我就来简单的讲下看大路的方法。 都是前辈教的,这里我只是简单复述一下。 大路的观察方法有以下几种: 先从庄闲的数量变化说起。 庄闲的强...

那女孩对我说
13分钟前
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部