1、JUC--volatile 关键字-内存可见性
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不具有原子性