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。
- 本文标签: Java 面试题
- 本文链接: https://www.jietongc.com/article/30
- 版权声明: 本文由大熊科技原创发布,转载请遵循《署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0)》许可协议授权