ICode9

精准搜索请尝试: 精确搜索
首页 > 系统相关> 文章详细

1、JUC--volatile 关键字-内存可见性

2019-04-29 20:43:02  阅读:267  来源: 互联网

标签:JUC ThreadDemo isFlag flag 线程 内存 volatile td public


Java JUC简介

Java 5.0 提供了 java.util.concurrent (简称
JUC )包,在此包中增加了在并发编程中很常用
的实用工具类,用于定义类似于线程的自定义子
系统,包括线程池、异步 IO 和轻量级任务框架。
提供可调的、灵活的线程池。还提供了设计用于
多线程上下文中的 Collection 实现等

 

线程实例:

public class TestVoatile {
    
    public static void main(String[] args) {
        ThreadDemo td = new ThreadDemo();
        
        new Thread(td).start();
        while(true){
            if(td.isFlag()){
                System.out.println("已启动");
                break;
            }
        }
    }

}


class ThreadDemo implements Runnable{
    
    private boolean flag = false;
    
    public boolean isFlag(){
        return flag;
    }
    
    public void setFlag(boolean flag){
        this.flag = flag;
    }

    @Override
    public void run() {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        flag = true;
        System.out.println("flag:" + isFlag());
    }
}

此时的main函数中是有两个线程的执行结果如下图所示:

此时执行的是第一个线程

while循环并没有执行

 

此时设计内存可见性的问题

共享数据

同时存在缓存的问题

此时线程1和main线程都有自己独立的缓存

对于线程1来说首先需要要调用主存中的值,首先需要读取值到线程1中

线程1读取值之后,并且要向主存中进行改值

此时main线程到来,取出主存中的值

所以此时main线程中的flag=false

但是此时并没有及时进行对主存进行修改值

 

此时使用线程睡眠:

        ThreadDemo td = new ThreadDemo();
        
        new Thread(td).start();
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        
        while(true){
            if(td.isFlag()){
                System.out.println("已启动");
                break;
            }
        }
    }

 

内存可见性问题

多个线程操作共享数据问题,彼此不可见

可以使用同步锁

在取值时进行刷新数据

public static void main(String[] args) {
        ThreadDemo td = new ThreadDemo();
        new Thread(td).start();
        while(true){
            synchronized (td) {
                if(td.isFlag()){
                    System.out.println("已启动");
                    break;
                }
            }
        }
    }

此时使用同步锁机制,效率极低

每次都会进行判断

如果一个正在使用数据,另一个线程就会等待

效率大大降低

 

volatile关键字:

当多个线程进行操作共享数据时,可以保证内存中的数据是可见的

可以理解成直接对主存中的数据进行操作

public class TestVoatile {
    
    public static void main(String[] args) {
        ThreadDemo td = new ThreadDemo();
        new Thread(td).start();

        while(true){
                if(td.isFlag()){
                    System.out.println("已启动");
                    break;
                }
        }
    }
}
class ThreadDemo implements Runnable{
    
    private volatile boolean flag = false;
    
    public boolean isFlag(){
        return flag;
    }
    
    public void setFlag(boolean flag){
        this.flag = flag;
    }

    @Override
    public void run() {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        flag = true;
        
        System.out.println("flag:" + isFlag());
    }
}

 

 

 

 

相对于synchronized:

Java 提供了一种稍弱的同步机制,即 volatile 变
量,用来确保将变量的更新操作通知到其他线程。
可以将 volatile 看做一个轻量级的锁

 

前者是一种轻量级的同部策略

1、volatile不具有互斥性(synchronized具有锁性值,只能有一个线程访问)

 2、volatile不具有原子性

 

标签:JUC,ThreadDemo,isFlag,flag,线程,内存,volatile,td,public
来源: https://www.cnblogs.com/Mrchengs/p/10792691.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有