栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

了解volitle关键字,死锁和线程交替输出案例

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

了解volitle关键字,死锁和线程交替输出案例

volitle

在JDK1.2 之前,Java的内存模型实现总是从主存(即共享内存)读取变量,是不需要进⾏特别的注意的。⽽在当前的 Java 内存模型中线程可以把变量保存本地内存(⽐如机器的寄存器)中,⽽不是直接在主存中进⾏读写。这就可能造成⼀个线程在主存中修改了⼀个变量的值,⽽另外⼀个线程还继续使⽤它在寄存器中的变量值的拷⻉,造成数据的不⼀致。

Java内存模型 JMM(Java Memory Moduel)
转载博客,详情请看

关键字volatile,指示 JVM,这个变量是不稳定的,每次使⽤它都到主存中进⾏读取。

保证共享变量可见性的两种方式:
(1)加锁

  • 线程获得锁
  • 清空当前工作内存
  • 从主内存中拷贝共享变量最新值到工作内存成为副本
  • 执行代码,如果更新了共享变量的值,刷新回主内存中
  • 释放锁
    (2)使用volatile修饰共享变量
  • 线程a从主内存读取共享变量到对应的工作内存
  • 对共享变量进行更改
  • 线程b读取共享变量的值到对应的工作内存
  • 线程a将修改后的值刷新到主内存,失效其他线程对共享变量的副本
  • 线程b对共享变量进行操作时,发现已经失效,重新从主内存读取最新值,放入到对应工作内存

volatile与synchronized的区别
volatile只能修饰实例变量和类变量,而可以synchronized修饰实例方法和代码块。

volatile保证数据的可见性,但是不能保证数据的原子性,而synchronized两者都能保证【是一种互斥机制】。

volatile可以禁止指令重排序,可以检查使用单例双重检查中对象创建时执行代码的乱序问题。

volatile可以看做是轻量版的synchronized,volatile不保证原子性,但是如果对一个共享变量进行多线程的纯赋值操作,那么就可以使用volatile代替synchronized,因为赋值本身是原子性的,而volatile保证了可见性,即可以保证是线程安全的。

1.死锁案例:

不同的线程占用对方需要的同步的资源不放弃, 都在等待对方放弃自己需要同步的资源,就形成了线程的死锁。如下面的例子:

public class DeadLock {

    public static void main(String[] args) {
        Service1 service1 = new Service1();
        Service2 service2 = new Service2();

        new Thread(()->{
            synchronized (Service1.class){
                service1.print();
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                synchronized (Service2.class){
                    service1.say();
                }
            }

        }).start();

        new Thread(()->{
            synchronized (Service2.class){
                service2.print();
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                synchronized (Service1.class){
                    service2.say();
                }
            }

        }).start();

    }
}

class Service1{

    public void print(){
        System.out.println("我是线程1");
    }

    public void say(){
        System.out.println("你好,线程2");
    }
}

线程都为阻塞状态,无法继续。

2.写一个线程交替输出案例(A线程循环输出A,B线程循环输出B,出现ABABABAB… )

交替打印’AB’

public class DemoABAB {
    public synchronized void printA() throws InterruptedException {
        System.out.print("A");
        this.notify();
        this.wait();
    }

    public synchronized void printB() throws InterruptedException {
        System.out.print("B");
        this.notify();
        this.wait();
    }

    public static void main(String[] args) {
        DemoABAB demoABAB = new DemoABAB();
        new Thread(()->{
            while (true){
                try {
                    demoABAB.printA();
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();

        new Thread(()->{
            while (true){
                try {
                    Thread.sleep(1000);
                    demoABAB.printB();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }
}
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/658694.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号