synchronized 能保证原子性。它通过获取和释放监视器锁,将代码块或方法标记为临界区,确保同一时刻只有一个线程能执行该段代码,从而把原本可能被打断的操作变成不可分割的整体。

为什么 synchronized 能实现原子性
因为 JVM 在执行 synchronized 块时,会先尝试获取对象监视器(Monitor)的锁。如果锁已被占用,当前线程会被阻塞;只有拿到锁后,才能进入临界区执行代码。执行完毕后,必须释放锁,其他等待的线程才能竞争锁。这种互斥机制保证了临界区内代码的原子性。

public class Counter {
private int count = 0;
public synchronized void increment() {
// 这个操作是原子的
count++;
}
public synchronized int getCount() {
return count;
}
public static void main(String[] args) throws InterruptedException {
Counter counter = new Counter();
Thread t1 = new Thread(() -> {
for (int i = 0; i < 10000; i++) {
counter.increment();
}
});
Thread t2 = new Thread(() -> {
for (int i = 0; i < 10000; i++) {
counter.increment();
}
});
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println("Final Count: " + counter.getCount());
}
}
预期输出:Final Count: 20000
立即学习“Java免费学习笔记(深入)”;
synchronized 的可见性与有序性保障
除了原子性,synchronized 还具备可见性和有序性。当线程释放锁时,会将工作内存中的变量刷新到主内存;当线程获取锁时,会清空工作内存并从主内存重新读取变量。这解决了多线程环境下的数据一致性问题。

public class VisibilityExample {
private boolean flag = false;
public synchronized void setFlag() {
flag = true;
}
public synchronized boolean isFlag() {
return flag;
}
public static void main(String[] args) throws InterruptedException {
VisibilityExample example = new VisibilityExample();
Thread writer = new Thread(() -> {
try { Thread.sleep(100); } catch (InterruptedException e) {}
example.setFlag();
});
Thread reader = new Thread(() -> {
while (!example.isFlag()) {
// 自旋等待
}
System.out.println("Flag is now true!");
});
writer.start();
reader.start();
writer.join();
reader.join();
}
}
预期输出:Flag is now true!
在复杂业务逻辑中如何保证原子性
当涉及多个变量的复合操作时,必须将所有相关操作放在同一个 synchronized 块内。例如,检查并更新状态的操作,如果分开加锁,仍可能出现竞态条件。因此,应将整个业务逻辑包裹在一个同步块中,确保其原子性。
public class ComplexOperation {
private int balance = 100;
private boolean overdraftAllowed = false;
public synchronized void withdraw(int amount) {
if (balance >= amount) {
balance -= amount;
System.out.println("Withdrawal successful. Balance: " + balance);
} else if (overdraftAllowed) {
balance -= amount;
System.out.println("Overdraft applied. Balance: " + balance);
} else {
System.out.println("Insufficient funds.");
}
}
public synchronized void allowOverdraft(boolean allowed) {
overdraftAllowed = allowed;
}
public static void main(String[] args) throws InterruptedException {
ComplexOperation op = new ComplexOperation();
Thread t1 = new Thread(() -> {
op.withdraw(50);
});
Thread t2 = new Thread(() -> {
op.allowOverdraft(true);
op.withdraw(60);
});
t1.start();
t2.start();
t1.join();
t2.join();
}
}
预期输出:Withdrawal successful. Balance: 50\nOverdraft applied. Balance: -10


















