You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java中能否在同步方法内定义同步代码块?请举例说明

Java同步方法内部能否定义同步代码块?

嘿,当然可以!Java不仅允许在synchronized方法内部定义synchronized代码块,这种写法在实际开发中还挺常见的——主要是为了更精细地控制锁的范围,或者利用内置锁的可重入特性来实现嵌套同步。

先给你理清楚核心逻辑:Java的内置锁(也就是对象锁)是可重入的,意思是如果一个线程已经持有某个对象的锁,那么它再次请求这个锁的时候不会被自己阻塞。这就为嵌套同步提供了基础。

下面给你两个常见的示例场景:

场景1:同步方法与内部代码块锁同一个对象(可重入演示)

这种情况里,同步方法默认锁的是当前对象(this),内部的同步代码块也显式锁this,线程可以顺利进入,不会发生死锁。

public class ReentrantLockDemo {
    // 同步方法,默认锁当前对象this
    public synchronized void outerSyncMethod() {
        System.out.println("进入同步方法,当前线程:" + Thread.currentThread().getName());
        
        // 内部定义同步代码块,锁同一个对象this
        synchronized (this) {
            System.out.println("进入内部同步代码块,当前线程:" + Thread.currentThread().getName());
            // 这里可以执行需要更细粒度同步的逻辑
            doSomething();
        }
        
        System.out.println("退出同步方法,当前线程:" + Thread.currentThread().getName());
    }
    
    private void doSomething() {
        // 模拟业务逻辑
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }
    
    public static void main(String[] args) {
        ReentrantLockDemo demo = new ReentrantLockDemo();
        // 启动两个线程测试
        new Thread(demo::outerSyncMethod, "线程A").start();
        new Thread(demo::outerSyncMethod, "线程B").start();
    }
}

运行这段代码你会看到,线程A先进入同步方法,然后顺利进入内部代码块,执行完后释放锁,线程B才会开始执行——完全符合预期,没有阻塞问题。

场景2:同步方法与内部代码块锁不同对象(细粒度锁控制)

有时候我们不想让整个方法都被锁死,只想对方法内的某一段代码加锁,或者需要锁另一个独立的对象来避免不必要的锁竞争,这时候就可以在同步方法内部用不同的锁对象。

public class DifferentLockDemo {
    // 定义一个独立的锁对象,用于内部代码块
    private final Object innerLock = new Object();
    
    // 同步方法,锁当前对象this
    public synchronized void outerSyncMethod() {
        System.out.println("进入同步方法,当前线程:" + Thread.currentThread().getName());
        
        // 这里是不需要同步的逻辑,比如一些只读操作
        System.out.println("执行非同步逻辑,当前线程:" + Thread.currentThread().getName());
        
        // 内部同步代码块,锁独立的innerLock对象
        synchronized (innerLock) {
            System.out.println("进入内部同步代码块(锁innerLock),当前线程:" + Thread.currentThread().getName());
            // 这里执行需要单独同步的逻辑,比如修改特定资源
            updateCriticalResource();
        }
        
        System.out.println("退出同步方法,当前线程:" + Thread.currentThread().getName());
    }
    
    private void updateCriticalResource() {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }
    
    public static void main(String[] args) {
        DifferentLockDemo demo = new DifferentLockDemo();
        new Thread(demo::outerSyncMethod, "线程X").start();
        new Thread(demo::outerSyncMethod, "线程Y").start();
    }
}

这个例子里,同步方法锁this,内部代码块锁innerLock,两者是独立的锁。这样设计的好处是,如果其他地方有只需要锁innerLock的逻辑,不会被this锁的竞争影响,提升了并发效率。

总结一下:

  • 允许在synchronized方法内部定义synchronized代码块,得益于Java内置锁的可重入性。
  • 可以选择锁同一个对象(利用可重入),或者不同对象(实现细粒度锁),根据业务需求灵活调整。

内容的提问来源于stack exchange,提问作者Karthik Reddy V V

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 08:55:27