极速越野摩托
76.51 MB · 2025-10-05
Synchronized是Java中最基本且最常用的线程同步机制,它能够有效解决多线程环境下的共享资源竞争问题。本文将全面解析Synchronized的工作原理、使用方式、优化策略以及实际应用场景。
Synchronized是Java语言原生支持的关键字,用于实现线程同步,保证多线程环境下对共享资源的安全访问。它的核心作用可以概括为三点:
不使用同步机制的典型后果是数据不一致。例如两个线程同时执行count++操作,由于count++实际上包含"读取-修改-写入"三个步骤,在并发情况下可能导致最终结果小于预期值
public synchronized void method() {
// 方法体
}
这种方式锁住的是当前实例对象(this),同一个实例的多个同步方法会互斥,不同实例的同步方法不会相互干扰。例如银行账户操作:
public class BankAccount {
private double balance;
public synchronized void deposit(double amount) {
balance += amount;
}
public synchronized void withdraw(double amount) {
balance -= amount;
}
}
public static synchronized void method() {
// 方法体
}
这种方式锁住的是类对象(Class对象),所有实例共享同一把锁,即使不同实例调用静态同步方法也会互斥。例如:
public class Counter {
private static int count = 0;
public static synchronized void increment() {
count++;
}
}
synchronized(obj) {
// 代码块
}
这种方式可以灵活指定锁对象,obj可以是任何对象实例。通常使用共享资源作为锁对象。例如:
public class TicketService {
private int tickets;
private final Object lock = new Object();
public void sellTicket() {
synchronized(lock) {
if(tickets > 0) {
tickets--;
}
}
}
}
synchronized(ClassName.class) {
// 代码块
}
这种方式同样锁住类对象,与静态同步方法效果相同。例如:
public class Logger {
public static void log(String message) {
synchronized(Logger.class) {
// 写入日志文件
}
}
}
Synchronized的底层实现依赖于JVM的对象监视器锁(Monitor)机制。每个Java对象都与一个Monitor相关联,Monitor包含以下关键字段:
_owner
:记录持有锁的线程_recursions
:锁的重入次数_EntryList
:存放等待锁的阻塞线程队列_WaitSet
:存放调用wait()后等待的线程队列当线程执行到同步代码块时:
monitorenter
指令尝试获取Monitor所有权monitorexit
指令,Monitor进入数-1对于同步方法,JVM通过方法访问标志ACC_SYNCHRONIZED
实现同步,原理与代码块同步类似
JDK1.6后对Synchronized进行了重大优化,引入了锁升级机制,根据竞争情况自动调整锁状态:
锁升级是不可逆的,一旦升级为重量级锁就无法降级
Synchronized是可重入锁,同一线程在外层方法获取锁后,内层方法可以直接再次获取该锁。JVM通过记录锁的持有线程和进入次数实现这一特性。例如:
public class ReentrantDemo {
public synchronized void method1() {
method2(); // 可重入
}
public synchronized void method2() {
// ...
}
}
一旦锁被其他线程获取,当前线程只能选择等待或阻塞,无法主动中断获取锁的过程。这与Lock类的可中断特性形成对比
Synchronized是非公平锁,不保证等待时间最长的线程优先获取锁,任何尝试获取锁的线程都有机会立即获取锁
public class Singleton {
private static volatile Singleton instance;
public static Singleton getInstance() {
if(instance == null) {
synchronized(Singleton.class) {
if(instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
public class SafeCounter {
private int count;
public synchronized void increment() {
count++;
}
}
public class ConnectionPool {
private List<Connection> pool = new ArrayList<>();
public synchronized Connection getConnection() {
if(pool.isEmpty()) return createConnection();
return pool.remove(pool.size()-1);
}
public synchronized void release(Connection conn) {
pool.add(conn);
}
}
public class PrivateLock {
private final Object lock = new Object();
public void method() {
synchronized(lock) {
// ...
}
}
}
特性 | Synchronized | volatile |
---|---|---|
原子性 | 保证代码块/方法的原子性 | 仅保证单次读/写的原子性 |
可见性 | 保证 | 保证 |
有序性 | 保证 | 有限保证 |
互斥性 | 支持 | 不支持 |
性能 | 较高开销 | 较低开销 |
使用复杂度 | 较高 | 较低 |
volatile适用于单一变量的可见性控制,而Synchronized适用于复杂操作的原子性控制
Synchronized作为Java最基本的同步机制,虽然存在一些性能缺陷,但在JDK不断优化下仍然是大多数并发场景的首选方案。理解其底层原理和适用场景,能够帮助开发者编写出更高效、更安全的并发程序。对于更复杂的并发需求,可以考虑结合Lock、CAS等机制实现