问答题975/1053同步方法和同步块,哪个是更好的选择?

难度:
2021-11-02 创建

参考答案:

在选择 同步方法同步块 时,需要根据具体的业务需求和代码逻辑来决定哪个更合适。这两者的主要区别在于锁的粒度控制的灵活性


同步方法

  • 特点

    • 锁的是整个方法,作用范围是整个方法体。
    • 锁的对象是调用该方法的对象实例(非静态方法)或类对象(静态方法)。
    • 简单易用,适合需要保证整个方法是线程安全的场景。
  • 优点

    1. 写法简单,易于理解。
    2. 避免遗漏同步逻辑,适合全部代码需要同步的场景。
  • 缺点

    1. 粒度较大,可能导致其他线程长时间等待,即使部分代码不需要加锁。
    2. 可能影响程序的性能,尤其是在高并发场景中。
  • 适用场景

    • 方法中所有代码都需要同步,例如涉及整体状态的修改操作。

示例

1public synchronized void increment() { 2 counter++; 3}

同步块

  • 特点

    • 锁的范围由代码块决定,作用范围更小、更灵活。
    • 锁的对象是开发者手动指定的,可以是任何对象(this、类对象或其他共享资源)。
  • 优点

    1. 粒度小,只有需要同步的代码部分才会加锁,提高了并发性能。
    2. 灵活性高,可以选择更具体的锁对象。
  • 缺点

    1. 写法复杂,可能因锁的选择不当导致线程安全问题。
    2. 如果锁的范围选择不恰当,可能会引入死锁等问题。
  • 适用场景

    • 只需对部分代码进行同步,而非整个方法。例如:读写分离、只同步共享资源访问部分。

示例

1public void increment() { 2 // 仅对共享变量加锁 3 synchronized (this) { 4 counter++; 5 } 6}

选择原则

  • 同步方法

    • 当方法中所有代码都需要线程安全且方法体较短时,使用同步方法更简单、清晰。
    • 适合简单场景,例如对共享计数器进行增减。
  • 同步块

    • 当方法中只有部分代码需要同步时,使用同步块可以减少锁的范围,提高性能。
    • 适合复杂逻辑或需要锁定特定资源的场景。

示例对比

1. 同步方法(锁粒度大)

1public synchronized void updateData() { 2 readData(); 3 processData(); 4 writeData(); 5}
  • 问题:即使 readData()processData() 不需要线程安全,也会受到锁的影响,降低了并发性能。

2. 同步块(锁粒度小)

1public void updateData() { 2 readData(); 3 processData(); 4 synchronized (this) { 5 writeData(); // 仅同步写操作 6 } 7}
  • 优势:锁只用于需要线程安全的部分,其他部分可以并行执行。

最近更新时间:2024-12-06