在Java中实现可见性(visibility)的主要方法详解

 更新时间:2023年08月07日 08:48:11   作者:Blue92120  
这篇文章主要介绍了在Java中实现可见性(visibility)的主要方法详解,在Java中,使用关键字volatile和使用锁(如synchronized关键字或 java.util.concurrent包中的锁)来确保对共享变量的修改在多线程环境中能够正确地被其他线程所观察到,需要的朋友可以参考下

可见性 visibility

在Java中,实现可见性(visibility)的主要方法是使用关键字volatile和使用锁(如synchronized关键字或 java.util.concurrent包中的锁)来确保对共享变量的修改在多线程环境中能够正确地被其他线程所观察到。

下面详细说明这两种方法,并附带代码演示。

1.使用volatile关键字:

volatile是一种轻量级的同步机制,用于告诉JVM对被修饰的变量不进行缓存,直接从主内存中读取和写入数据。

这样可以确保当一个线程修改了变量的值时,其他线程能够立即看到这个变化,而不是使用缓存中的旧值。

public class VolatileVisibilityExample {
    private volatile boolean flag = false;
    public void setFlag(boolean value) {
        flag = value;
    }
    public void checkFlag() {
        while (!flag) {
            // Busy waiting until the flag becomes true
        }
        System.out.println("Flag is now true!");
    }
    public static void main(String[] args) {
        VolatileVisibilityExample example = new VolatileVisibilityExample();
        new Thread(() -> {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            example.setFlag(true);
        }).start();
        new Thread(() -> {
            example.checkFlag();
        }).start();
    }
}

在上面的例子中,我们创建了一个VolatileVisibilityExample类,其中的flag变量被声明为volatile。

第一个线程在启动后会等待1秒钟然后将flag设置为true,而第二个线程在flag变为true之前会一直进行忙等待(busy waiting)。

由于flag是volatile的,第二个线程能够看到第一个线程对flag的修改,并在flag变为true时结束忙等待。

2.使用锁:

另一种实现可见性的方法是使用锁,通过synchronized关键字或者java.util.concurrent包中的锁机制来保护对共享变量的访问。

public class LockVisibilityExample {
    private boolean flag = false;
    private final Object lock = new Object();
    public void setFlag(boolean value) {
        synchronized (lock) {
            flag = value;
        }
    }
    public void checkFlag() {
        synchronized (lock) {
            while (!flag) {
                try {
                    lock.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
        System.out.println("Flag is now true!");
    }
    public static void main(String[] args) {
        LockVisibilityExample example = new LockVisibilityExample();
        new Thread(() -> {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            example.setFlag(true);
            synchronized (example.lock) {
                example.lock.notifyAll();
            }
        }).start();
        new Thread(() -> {
            example.checkFlag();
        }).start();
    }
}

在上面的例子中,我们创建了一个LockVisibilityExample类,其中使用了一个名为lock的对象作为锁。

在setFlag和checkFlag方法中,我们使用synchronized关键字来保护对flag的访问。

第一个线程设置flag为true并通过synchronized块的notifyAll()方法通知第二个线程,而第二个线程则在flag变为true之前一直等待,并在被通知后结束等待。

这两种方法都可以实现可见性,但使用volatile更为简单和轻量级。

然而,在某些情况下,使用锁可能会更有优势,例如需要进行更复杂的操作或需要更精细地控制对共享资源的访问。

到此这篇关于在Java中实现可见性(visibility)的主要方法详解的文章就介绍到这了,更多相关Java中实现可见性内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • SpringBoot整合InfluxDB的详细过程

    SpringBoot整合InfluxDB的详细过程

    InfluxDB是一个开源的时间序列数据库,由Go语言编写,适用于存储和查询按时间顺序产生的数据,它具有高效的数据存储和查询机制,支持高并发写入和查询,灵活的数据模型和强大的查询语言,本文介绍SpringBoot整合InfluxDB的详细过程,感兴趣的朋友一起看看吧
    2024-12-12
  • Spring HTTP缓存应用场景举例

    Spring HTTP缓存应用场景举例

    这篇文章详细介绍了Spring Framework中HTTP缓存的基本概念和实现方式,包括Cache-Control头、条件请求(ETag/Last-Modified)、CacheControl类的使用,以及在控制器和静态资源中应用HTTP缓存,本文结合实例代码给大家介绍的非常详细,感兴趣的朋友一起看看吧
    2025-11-11
  • SpringBoot 启动流程追踪方法分享

    SpringBoot 启动流程追踪方法分享

    这篇文章主要介绍了SpringBoot 启动流程追踪方法分享的相关资料,需要的朋友可以参考下
    2023-08-08
  • Java Swing实现餐厅点餐系统源码(收藏版)

    Java Swing实现餐厅点餐系统源码(收藏版)

    这篇文章主要介绍了Java Swing实现餐厅点餐系统源码,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-02-02
  • springmvc如何使用POJO作为参数

    springmvc如何使用POJO作为参数

    这篇文章主要介绍了springmvc如何使用POJO作为参数,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-01-01
  • JVM加载一个类的过程

    JVM加载一个类的过程

    本文主要介绍了JVM加载一个类的过程。具有很好的参考价值,下面跟着小编一起来看下吧
    2017-02-02
  • SpringBoot项目实现分布式日志链路追踪

    SpringBoot项目实现分布式日志链路追踪

    这篇文章主要给大家介绍了Spring Boot项目如何实现分布式日志链路追踪,文中通过代码示例给大家介绍的非常详细,需要的朋友可以参考下
    2023-07-07
  • Java 多线程死锁的产生以及如何避免死锁

    Java 多线程死锁的产生以及如何避免死锁

    这篇文章主要介绍了Java 多线程死锁的产生以及如何避免死锁,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-09-09
  • Java实现DelayQueue延迟队列示例代码

    Java实现DelayQueue延迟队列示例代码

    Java中的DelayQueue是一个特殊的队列,它只允许在指定的延迟时间之后才能从队列中取出元素,这篇文章主要给大家介绍了关于Java实现DelayQueue延迟队列的相关资料,需要的朋友可以参考下
    2025-07-07
  • SpringBoot基于FFmpeg实现压缩视频切片为m3u8

    SpringBoot基于FFmpeg实现压缩视频切片为m3u8

    本文介绍了一个使用FFmpeg将MP4视频压缩切片为HLS格式M3U8文件的Java工具类,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下
    2026-02-02

最新评论