跳转到内容

Synchronized关键字

来自代码酷
Admin留言 | 贡献2025年5月12日 (一) 00:26的版本 (Page creation by admin bot)

(差异) ←上一版本 | 已核准修订 (差异) | 最后版本 (差异) | 下一版本→ (差异)

模板:Note

概述[编辑 | 编辑源代码]

synchronized是Java中用于实现线程同步的关键字,它能够确保同一时刻只有一个线程可以访问被同步的代码块或方法,从而解决多线程环境下的数据竞争问题。其核心功能包括:

  • 原子性:保证操作的不可分割性。
  • 可见性:确保线程对共享变量的修改对其他线程立即可见。
  • 有序性:防止指令重排序导致的并发问题。

语法形式[编辑 | 编辑源代码]

`synchronized`可通过以下三种方式使用:

1. 同步实例方法[编辑 | 编辑源代码]

修饰非静态方法,锁对象是当前实例(`this`)。

public synchronized void increment() {
    // 线程安全的代码
}

2. 同步静态方法[编辑 | 编辑源代码]

修饰静态方法,锁对象是当前类的`Class`对象。

public static synchronized void staticIncrement() {
    // 线程安全的静态方法
}

3. 同步代码块[编辑 | 编辑源代码]

指定任意对象作为锁,灵活性更高。

public void blockSync() {
    synchronized (lockObject) {
        // 线程安全的代码块
    }
}

底层原理[编辑 | 编辑源代码]

`synchronized`通过JVM内置的监视器锁(Monitor)实现,其工作流程如下:

flowchart TD A[线程尝试获取锁] --> B{锁是否空闲?} B -->|是| C[获取锁并进入临界区] B -->|否| D[进入阻塞队列等待] C --> E[执行同步代码] E --> F[释放锁并唤醒等待线程]

  • JDK 1.6后引入锁优化机制,包括:
 * 偏向锁(Biased Locking)
 * 轻量级锁(Lightweight Locking)
 * 自旋锁(Spin Locking)
 * 锁消除(Lock Elimination)

代码示例[编辑 | 编辑源代码]

计数器案例[编辑 | 编辑源代码]

以下示例展示未同步和同步的计数器区别:

class UnsafeCounter {
    private int count = 0;
    
    public void add() {
        count++; // 非原子操作
    }
}

class SafeCounter {
    private int count = 0;
    
    public synchronized void add() {
        count++; // 原子操作
    }
}

执行测试代码:

public static void main(String[] args) throws InterruptedException {
    final SafeCounter safe = new SafeCounter();
    final UnsafeCounter unsafe = new UnsafeCounter();
    
    Runnable task = () -> {
        for (int i = 0; i < 1000; i++) {
            safe.add();
            unsafe.add();
        }
    };

    Thread t1 = new Thread(task);
    Thread t2 = new Thread(task);
    
    t1.start();
    t2.start();
    t1.join();
    t2.join();
    
    System.out.println("SafeCounter: " + safe.getCount());   // 输出2000
    System.out.println("UnsafeCounter: " + unsafe.getCount()); // 可能小于2000
}

锁的存储结构[编辑 | 编辑源代码]

对象头中的Mark Word存储锁状态信息:

classDiagram class MarkWord { +hashcode: 25bit +age: 4bit +biased_lock: 1bit +lock: 2bit }

锁状态转换关系: 无锁偏向锁轻量级锁重量级锁

实际应用场景[编辑 | 编辑源代码]

1. 单例模式实现[编辑 | 编辑源代码]

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;
    }
}

2. 线程安全集合包装[编辑 | 编辑源代码]

List<String> syncList = Collections.synchronizedList(new ArrayList<>());

注意事项[编辑 | 编辑源代码]

  • 避免锁粒度过大(如直接同步整个方法)
  • 防止死锁(按固定顺序获取多把锁)
  • 优先使用`java.util.concurrent`包中的高级工具类

性能对比[编辑 | 编辑源代码]

不同同步方式性能比较(纳秒/操作)
同步方式 JDK 1.6 JDK 11
无同步 5 3
synchronized 20 15
ReentrantLock 18 12

常见问题[编辑 | 编辑源代码]

模板:Q&A

模板:Q&A