• synchronized 关键字和 volatile 关键字有什么区别?


    synchronized 关键字和 volatile 关键字有什么区别?

    在 Java 中,synchronized 关键字和 volatile 关键字都可以用来实现线程安全,但是它们有不同的用途和实现方式。本文将介绍 synchronized 关键字和 volatile 关键字的区别,包括它们的使用场景、实现机制和效果比较。

    在这里插入图片描述

    synchronized 关键字

    synchronized 是 Java 中的一种同步机制,用于实现多线程之间的同步。synchronized 关键字可以用于方法和代码块中,用于保护共享资源的访问,防止多个线程同时访问和修改共享资源,从而保证线程安全。synchronized 关键字的使用方式如下:

    1. 同步方法

    在方法声明中使用 synchronized 关键字,可以将整个方法作为同步代码块,保证多个线程不会同时访问该方法。

    public synchronized void doSomething() {
        // 线程安全的代码
    }
    
    • 1
    • 2
    • 3

    2. 同步代码块

    在代码块中使用 synchronized 关键字,可以将该代码块作为同步代码块,保证多个线程不会同时访问该代码块。

    public void doSomething() {
        synchronized (this) {
            // 线程安全的代码
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    在 synchronized 关键字中,需要指定一个锁对象,该对象可以是任意的 Java 对象,用于保护共享资源的访问。在同步代码块中,通常使用 this 关键字作为锁对象,表示当前对象。在同步方法中,锁对象为当前对象的实例。

    synchronized 关键字的实现机制是基于 Java 中的内置锁(也称为监视器锁)实现的。Java 中的每个对象都有一个内置锁,可以用于实现同步。当一个线程需要访问共享资源时,它需要获取该资源的锁,如果锁已经被其他线程获取,则该线程会被阻塞,直到锁被释放。当一个线程释放锁时,等待该锁的线程会被唤醒,继续竞争锁。

    synchronized 关键字的使用可以保证线程安全,但是它也有一些缺点。首先,如果多个线程频繁地竞争同一个锁,会导致性能问题,因为只有一个线程可以获得锁,其他线程需要等待。其次,如果同步代码块中的代码执行时间过长,也会导致性能问题,因为其他线程需要等待长时间才能访问共享资源。

    volatile 关键字

    volatile 是 Java 中的一种关键字,用于修饰变量,用于保证变量的可见性和有序性。volatile 关键字可以用于单个变量和数组中的元素,用于保证它们的访问不会受到缓存和优化等因素的影响,从而保证线程安全。volatile 关键字的使用方式如下:

    public class Test {
        private volatile int count = 0;
    
        public void increment() {
            count++;
        }
    
        public int getCount() {
            return count;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    在上面的代码中,count 变量被声明为 volatile,在 increment 方法中对 count 变量进行递增操作。由于 count 变量是 volatile 的,因此它保证了对 count 变量的访问不会受到缓存和优化等因素的影响,从而保证了线程安全。

    volatile 关键字的实现机制是基于 CPU 缓存一致性协议实现的。在多核 CPU 中,每个核都有自己的缓存,缓存中保存了最近访问的数据。如果多个 CPU 访问同一个变量时,它们可能会使用自己的缓存,导致数据不一致。为了解决这个问题,CPU 提供了缓存一致性协议(如 MESI),用于保证不同缓存中的数据一致。当一个 CPU 修改了变量时,它会通知其他 CPU,让它们更新自己的缓存中的数据。

    volatile 关键字的使用可以保证变量的可见性和有序性,但是它也有一些限制。首先,volatile 关键字只能保证单个变量的原子性,不能保证多个变量的原子性。其次,volatile 关键字不能保证线程安全,因为它不能保证多个线程之间的操作顺序。如果需要保证多个操作的原子性和顺序,需要使用 synchronized 关键字或者其他的同步机制。

    synchronized 关键字和 volatile 关键字的区别

    synchronized 关键字和 volatile 关键字都可以用于实现线程安全,但是它们有不同的用途和实现方式。下面是它们之间的区别:

    1. 实现机制

    synchronized 关键字是基于内置锁实现的,使用锁对象来保护共享资源的访问。volatile 关键字是基于 CPU 缓存一致性协议实现的,用于保证变量的可见性和有序性。

    2. 适用范围

    synchronized 关键字可以用于任何需要保证线程安全的代码块和方法中,包括对共享资源的读取和写入操作。volatile 关键字只适用于对单个变量的读取和写入操作。

    3. 原子性

    synchronized 关键字可以保证多个操作的原子性,包括对共享资源的读取和写入操作。volatile 关键字只能保证单个变量的原子性。

    4. 顺序性

    synchronized 关键字可以保证多个操作之间的顺序性,因为同步代码块中的代码是串行执行的。volatile 关键字不能保证多个操作之间的顺序性,因为它只保证了对变量的访问顺序,不能保证多个操作之间的执行顺序。

    5. 性能

    synchronized 关键字在竞争激烈的情况下会导致性能问题,因为只有一个线程可以获得锁,其他线程需要等待。volatile 关键字的性能比 synchronized 关键字好,因为它不需要获取锁。

    综上所述,synchronized 关键字和 volatile 关键字都可以用于实现线程安全,但是它们有不同的用途和实现方式。如果需要保证多个操作的原子性和顺序性,建议使用 synchronized 关键字;如果只需要保证单个变量的可见性和有序性,可以使用 volatile 关键字。

  • 相关阅读:
    限时开发、码力全开、2w奖金!AGI Hackathon等你挑战!
    深度解读《深度探索C++对象模型》之拷贝构造函数
    视频模板SDK,为企业带来无限创意与效率
    React Hooks、useState、useEffect 、react函数状态
    JAVAWeb--会话_过滤器_监听器
    Rest风格操作
    聊聊Go语言的向前兼容性和toolchain规则
    【单调栈】503. 下一个更大元素 II
    高等数学(第七版)同济大学 习题7-3 个人解答
    从0开始python学习-29.selenium 通过cookie信息进行登录
  • 原文地址:https://blog.csdn.net/2302_77835532/article/details/130887343