在 Java 中,线程安全需要保证以下三个核心特性:
1. 原子性(Atomicity)
原子性是指一个操作是不可分割的,要么全部执行成功,要么全部不执行。如果一个操作是原子的,那么在多线程环境下,不会出现部分执行的情况。
如何保证原子性:
- 使用
synchronized关键字。 - 使用
java.util.concurrent.atomic包中的原子类(如AtomicInteger、AtomicReference等)。 - 使用锁机制(如
ReentrantLock)。
示例:
import java.util.concurrent.atomic.AtomicInteger;
public class AtomicityExample {
private AtomicInteger counter = new AtomicInteger(0);
public void increment() {
counter.incrementAndGet(); // 原子操作
}
public int getCounter() {
return counter.get();
}
public static void main(String[] args) throws InterruptedException {
AtomicityExample example = new AtomicityExample();
Thread t1 = new Thread(() -> {
for (int i = 0; i < 1000; i++) {
example.increment();
}
});
Thread t2 = new Thread(() -> {
for (int i = 0; i < 1000; i++) {
example.increment();
}
});
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println("Counter: " + example.getCounter()); // 输出 2000
}
}
2. 可见性(Visibility)
可见性是指一个线程对共享变量的修改能够及时被其他线程看到。如果没有可见性保证,一个线程的修改可能对其他线程不可见,导致数据不一致。
如何保证可见性:
- 使用
volatile关键字。 - 使用
synchronized关键字。 - 使用
java.util.concurrent包中的工具类(如ReentrantLock、CountDownLatch等)。
示例:
class SharedResource {
private volatile boolean flag = false; // 使用 volatile 保证可见性
public void setFlag(boolean flag) {
this.flag = flag;
}
public boolean getFlag() {
return flag;
}
}
public class VisibilityExample {
public static void main(String[] args) {
SharedResource shared = new SharedResource();
Thread writerThread = new Thread(() -> {
try {
Thread.sleep(1000); // 模拟耗时操作
shared.setFlag(true);
System.out.println("Flag set to true by writer thread.");
} catch (InterruptedException e) {
e.printStackTrace();
}
});
Thread readerThread = new Thread(() -> {
while (!shared.getFlag()) {
// 等待 flag 变为 true
}
System.out.println("Flag is true, reader thread exiting.");
});
writerThread.start();
readerThread.start();
}
}
3. 有序性(Ordering)
有序性是指程序执行的顺序按照代码的先后顺序执行。在多线程环境下,由于指令重排序(JVM 或 CPU 优化),代码的执行顺序可能与编写顺序不一致,导致线程安全问题。
如何保证有序性:
- 使用
volatile关键字(禁止指令重排序)。 - 使用
synchronized关键字。 - 使用
final关键字(保证构造函数的正确初始化顺序)。
示例:
class Singleton {
private static volatile Singleton instance; // 使用 volatile 保证有序性
private Singleton() {}
public static Singleton getInstance() {
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton(); // 避免指令重排序
}
}
}
return instance;
}
}
public class OrderingExample {
public static void main(String[] args) {
Singleton singleton = Singleton.getInstance();
System.out.println("Singleton instance created: " + singleton);
}
}
总结
为了保证线程安全,必须同时满足以下三个特性:
- 原子性:操作不可分割。
- 可见性:一个线程的修改对其他线程可见。
- 有序性:代码执行顺序符合预期。
在实际开发中,可以通过以下方式实现线程安全:
- 使用
synchronized关键字。 - 使用
volatile关键字。 - 使用
java.util.concurrent包中的工具类(如AtomicInteger、ReentrantLock等)。 - 使用不可变对象(
final关键字)。
1万+



被折叠的 条评论
为什么被折叠?



