美文网首页
002--volatile 关键字-内存可见性

002--volatile 关键字-内存可见性

作者: 糖纸疯了 | 来源:发表于2018-05-04 17:33 被阅读27次

话题一:多线程的3种创建方式

Java使用Thread类代表线程,所有的线程对象都必须是Thread类或其子类的实例。Java可以用三种方式来创建线程,如下所示:
1)继承Thread类创建线程
2)实现Runnable接口创建线程
3)使用Callable和Future创建线程


话题二:wait和notify的理解与使用

  • 案例分析wait和notify

  • wait和notify知识补充:首先要理解notify()和wait(),因为这两个方法本来就不属于Thread类,而是属于最底层的object基础类的,也就是说不光是Thread,每个对象都有notify和wait的功能,为什么

因为他们是用来操纵锁的,而每个对象都有锁,锁是每个对象的基础,既然锁是基础的,那么操纵锁的方法当然也是最基础了.


话题三:同样是线程休眠:wait(),sleep(),suspend()有什么区别呢?

  • wait:让当前线程阻塞,同时又“积极”地等待条件发生改变,这一点很关键,sleep和suspend无法做到.
    1)因为我们有时候需要通过同步(synchronized)的帮助来防止线程之间的冲突,而一旦使用同步,就要锁定对象,也就是获取对象锁,其它要使用该对象锁的线程都只能排队等着,等到同步方法或者同步块里的程序全部运行完才有机会.在同步方法和同步块中,无论sleep()还是suspend()都不可能自己被调用的时候解除锁定,他们都霸占着正在使用的对象锁不放

    2) 而wait却可以,它可以让同步方法或者同步块暂时放弃对象锁,而将它暂时让给其它需要对象锁的人(这里应该是程序块,或线程)用,这意味着可在执行wait()期间调用线程对象中的其他同步方法!在其它情况下(sleep啊,suspend啊),这是不可能的.

    3) 但是注意我前面说的,只是暂时放弃对象锁,暂时给其它线程使用,我wait所在的线程还是要把这个对象锁收回来的!

  • sleep:

  • suspend:


话题四:wait()暂时放弃对象锁后,如何将对象锁收回来?

  • 第一种方法,限定借出去的时间.在wait()中设置参数,比如wait(1000),以毫秒为单位,就表明我只借出去1秒中,一秒钟之后,我自动收回:wait(long timeout);
  • 第二种方法,让借出去的人通知我,他用完了,要还给我了.这时,我马上就收回来:notify();
  • PS:.哎,假如我设了1小时之后收回,别人只用了半小时就完了,那怎么办呢?靠!当然用完了就收回了,还管我设的是多长时间啊!

话题五:线程的可用方法展示

  • notify():通知
  • wait():等待
  • run():执行
查看Thread线程的方法

话题六:synchronized和volatile?

1.volatile问题引出

// 老师演示的时候,有一个问题,虽然子线程falg=true,但是main线程打印依然是false!但是在我的JDK上没有重现这一个现象
public class TestVolatile {
    public static void main(String[] args) throws Exception {
        // 1.创建一个线程
        MyThreadA myThreadA = new MyThreadA();
        new Thread(myThreadA).start();
        new Thread(myThreadA).start();
        
        // 2.mian主线程
        while(true){
            if (myThreadA.flag) {
                System.out.println("-------------主线程flag:"+myThreadA.flag);
                Thread.sleep(1000);
            }else{
                System.out.println("*************主线程flag:"+myThreadA.flag);
                Thread.sleep(1000);
            }
        }
    }
}
class MyThreadA implements Runnable{
    public boolean flag = Boolean.FALSE;
    
    @Override
    public void run() {
        try {
            System.out.println("-----------自定义线程执行休眠1s");
            Thread.sleep(200);
            flag = Boolean.TRUE;
            System.out.println("-----------休眠结束flag:"+flag);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

2.synchronized(object){}代表什么含义?
- 只能由一个线程同时使用object
- 多线程时,先判断锁,有锁就要将后续线程阻塞挂起,直到下一次CPU重新给他进行任务分配
- 加锁的这种效率是最低的!但是又需要刷新数据(内存可见性的问题),怎么办?--volatile
- volatile可以保证多个线程在访问相同数据时候,数据是实时可见的(实时将缓存数据刷新到主存中)!


3.synchronized和volatile比较
- volatile对比于synchronized,是一种轻量级的同步策略!
- volatile不具备"互斥性",不能保证只有一个线程使用共享数据
- volatile不能保证变量的原子性


4.什么是原子性?

  i++ 的原子性问题:i++ 的操作实际上分为三个步骤“读-改-写”
  int i = 10;
  i = i++; //10

  int temp = i;
  i = i + 1;
  i = temp;
- 本身来说,i++不能将过程进行拆解,但是volatile不能保证原子性,如果在多线程下就会被拆开,数据的执行结果就会出错!

相关文章

  • 002--volatile 关键字-内存可见性

    话题一:多线程的3种创建方式 Java使用Thread类代表线程,所有的线程对象都必须是Thread类或其子类的实...

  • 面试题收集

    Synchronized关键字和ReentrantLock的对比相同点:互斥性、内存可见性、可重入 不同点: ①R...

  • 深入浅出 Java 并发编程 (2)

    本文目录 Java 内存模型与可见性 指令重排序 使用 volatile 关键字保证可见性 使用 synchron...

  • 小编带您Volatile的详解

    volatile关键字修饰的共享变量主要有两个特点:1.保证了不同线程访问的内存可见性 2.禁止重排序 在说内存可...

  • Java之Volatile轻量级同步使用

    volatile关键字有两个特性 内存可见性java内存模型规定对于多个线程共享的内存变量,是存储在主内存当中。每...

  • 深度解析volatile—底层实现

    我们都知道,Java关键字volatile的作用 1、内存可见性2、禁止指令重排序 可见性是指,在多线程环境,共享...

  • Java并发基础

    volatile关键字 保证共享变量的可见性 使用Lock指令保证可见性a.引起处理器缓存回写到内存b.处理器缓存...

  • 多线程 | Volatile到底有什么用?

    Volatile的作用: 保持内存可见性.内存可见性:多个线程操作同一个变量,可确保写线程更新变量,其他读线程可以...

  • 深入理解 volatile 关键字原理

    1. 基本概念 volatile 关键字,具有两个特性:1. 内存的可见性, 2. 禁止指令重排序优化。 内存可见...

  • volatile实现

    volatile关键字有两方面的作用,一是保证共享变量可见性,二是禁止指令重排。 一、内存可见性 站在一个java...

网友评论

      本文标题:002--volatile 关键字-内存可见性

      本文链接:https://www.haomeiwen.com/subject/lrllrftx.html