synchronized

**synchronized** 是 Java 中的一个关键字,用于实现线程同步,确保多个线程在访问共享资源时的线程安全。它的主要作用是防止多个线程同时执行某个代码块或方法,从而避免数据不一致或竞态条件(Race Condition)的问题。


synchronized 的作用

  1. 线程安全:确保同一时间只有一个线程可以访问被 synchronized 修饰的代码块或方法。
  2. 可见性:保证线程对共享变量的修改对其他线程是可见的(通过内存屏障实现)。
  3. 原子性:确保被 synchronized 保护的代码块或方法是一个不可分割的操作。

synchronized 的用法

synchronized 可以用于以下两种场景:

1. 修饰实例方法
  • 锁对象是当前实例(this)。
  • 同一时间只有一个线程可以执行该实例的 synchronized 方法。
public class Counter {
    private int count = 0;

    // synchronized 修饰实例方法
    public synchronized void increment() {
        count++;
    }

    public int getCount() {
        return count;
    }
}

解释

  • 多个线程调用同一个 Counter 实例的 increment() 方法时,只有一个线程可以执行该方法,其他线程需要等待。

2. 修饰静态方法
  • 锁对象是当前类的 Class 对象(Counter.class)。
  • 同一时间只有一个线程可以执行该类的 synchronized 静态方法。
public class Counter {
    private static int count = 0;

    // synchronized 修饰静态方法
    public static synchronized void increment() {
        count++;
    }

    public static int getCount() {
        return count;
    }
}

解释

  • 多个线程调用 Counter.increment() 时,只有一个线程可以执行该方法,其他线程需要等待。

3. 修饰代码块
  • 可以指定锁对象(可以是任意对象)。
  • 更细粒度的控制,减少锁的竞争。
public class Counter {
    private int count = 0;
    private final Object lock = new Object(); // 锁对象

    public void increment() {
        // synchronized 修饰代码块
        synchronized (lock) {
            count++;
        }
    }

    public int getCount() {
        return count;
    }
}

解释

  • 只有获取到 lock 对象的线程才能执行 synchronized 代码块中的内容。

synchronized 的工作原理

  1. 锁机制
    • 每个 Java 对象都有一个内置锁(Monitor Lock),也称为监视器锁。
    • 当一个线程进入 synchronized 代码块或方法时,它会尝试获取锁;如果锁已被其他线程持有,则当前线程进入阻塞状态,直到锁被释放。
  2. 锁的释放
    • 当线程执行完 synchronized 代码块或方法后,会自动释放锁。
    • 即使代码块中抛出异常,锁也会被释放。

synchronized 的优缺点

优点
  • 简单易用:Java 语言原生支持,无需额外依赖。
  • 自动管理锁的获取和释放,避免死锁(在正确使用的情况下)。
缺点
  • 性能开销:线程竞争锁时会导致上下文切换和阻塞,影响性能。
  • 粒度较粗:如果锁的范围过大,可能会导致并发性能下降。

synchronized 与其他锁机制的对比

特性synchronizedReentrantLock
锁类型内置锁(JVM 实现)显式锁(Java 代码实现)
灵活性较低较高(支持公平锁、可中断锁等)
性能在低竞争场景下性能较好在高竞争场景下性能较好
锁释放自动释放需要手动调用 unlock()

示例:synchronized 的实际应用

以下是一个使用 synchronized 实现线程安全的计数器:

public class SynchronizedExample {
    private int count = 0;

    public synchronized void increment() {
        count++;
    }

    public int getCount() {
        return count;
    }

    public static void main(String[] args) throws InterruptedException {
        SynchronizedExample example = new SynchronizedExample();

        // 创建多个线程并发调用 increment()
        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("Final count: " + example.getCount()); // 输出 2000
    }
}

解释

  • 两个线程并发调用 increment() 方法,但由于 synchronized 的保护,最终结果是正确的(2000)。

总结

  • synchronized 是 Java 中实现线程同步的基本工具。
  • 它通过锁机制确保线程安全,但需要注意锁的粒度和性能开销。
  • 在高并发场景下,可以考虑使用 ReentrantLock 等更灵活的锁机制。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值