原创

java面试题-深入理解Java中synchronized和volatile关键字的作用

在Java多线程编程中,synchronized和volatile关键字是处理并发访问的重要工具。本文将深入讨论这两个关键字的作用、区别以及如何正确使用它们来确保线程安全性,并提供相应的代码演示。

1. volatile关键字的作用

volatile关键字主要用于两个方面:

1.1 可见性

当一个共享变量被volatile修饰后,保证了不同线程对该变量进行操作时的可见性。换句话说,当一个线程修改了该变量的值,新值对其他线程来说是立即可见的,而不会出现线程间的数据不一致问题。

1.2 禁止指令重排序

volatile关键字还禁止了指令重排序,确保了操作的有序性。这就意味着volatile变量的读写操作不会被重排序,保证了线程按照代码顺序执行。

public class VolatileExample {
    private volatile boolean flag = false;

    public void setFlag() {
        flag = true;
    }

    public void printFlag() {
        while (!flag) {
            // Busy-waiting
        }
        System.out.println("Flag is true!");
    }
}

2. synchronized关键字的作用

synchronized关键字用于保证多个线程对共享资源的互斥访问,它的作用有以下几个方面:

2.1 保证变量的修改可见性和原子性

synchronized关键字可以用于方法、代码块和静态方法,分别锁定对象实例、对象实例的代码块和类。通过synchronized,可以确保对变量的修改在多线程环境下是可见的,并且保证了对变量的原子性操作。

public class SynchronizedExample {
    private int counter = 0;

    public synchronized void increment() {
        counter++;
    }
}

2.2 防止并发导致的数据不一致

synchronized关键字可以防止多个线程同时执行同步方法或同步代码块,从而避免了并发导致的数据不一致问题。

public class SynchronizedExample {
    private int counter = 0;

    public synchronized void increment() {
        counter++;
    }
}

3. 区别与使用场景

3.1 区别

volatile仅能使用在变量级别,而synchronized可以用于变量、方法和类级别。
volatile保证了变量的修改可见性,但不能保证原子性;而synchronized可以同时保证变量的修改可见性和原子性。
volatile不会造成线程阻塞,而synchronized可能会导致线程阻塞。
volatile标记的变量不会被编译器优化,而synchronized标记的变量可能会被编译器优化。

3.2 使用场景

当变量的写入操作不依赖于变量的当前值,或确保只有单个线程更新变量的值时,可以使用volatile。
当需要保证变量的修改可见性和原子性时,或存在复杂的同步需求时,应该使用synchronized。

正文到此结束
本文目录