java monitor locked_Java 中 lock 和 monitor 的区别 · Kwritin

[ java lock monitor ]

Java 提供多种机制供线程间交互。最基本的方式是同步(synchronzation)。

同步可以通过 monitor 来实现,每一个 java 对象包含一个 monitor ,线程可以在上面 lock 和 unlock。

java 1.5 之后,同步还可以通过 juc api 来实现。Synchronization is built around an internal entity known as the intrinsic lock or monitor lock.

Every object has an intrinsic lock associated with it. By convention, a thread has to acquire the object’s monitor lock before accessing them, and then release the monitor lock when it’s done with them. A thread is said to own the lock between the time it has acquired the lock and released the lock.

As long as a thread owns a monitor lock, no other thread can acquire the same lock. The other thread will block when it attempts to acquire the lock.

When a thread releases the lock, a happens-before relationship is established between that action and any subsequent acquisition of the same lock.

翻译一下就是:synchronization(同步)是基于 java 的 内置锁 ,又叫 monitor 锁 来实现的。

每个对象都内置了一把锁 (monitor lock)。

通常,一个线程在使用某个对象之前,需要先获得它的内置锁,使用之后再释放内置锁。

这叫做锁的获取和释放。

当线程获得了锁之后,其他线程无法再获取这一把锁,它们会在获取时阻塞。

当线程释放锁之后,其余获取操作就和当前的释放操作构成 happens-before 关系。保证逻辑顺序性。

在 java 1.5 版本之前,没有提供 lock 相关 api ,写并发程序只能依靠 synchronized 关键字和 Object 上的 wait, notify, notifyAll 方法,背后依赖的也就是 monitor lock (intrinsic)。

monitor lock 位于 Java 对象的对象头中。

对象头上有若干标志位,记录当前对象锁定状态以及被哪个线程拥有。

随着 1.5 版本发布,java 新增的 juc 工具包提供了大量接口,旨在完善 java 多线程编程。从以前的隐式调用 intrinsic lock 扩展到现式使用 lock api。

新的 juc 除了 lock 以外,还提供:原子变量、并发集合、同步器、Executor 框架等。

lock 相关的新特性实现从关键字使用到 api 调用:增加编程灵活、可控,赋予开发者更多权力

锁的状态查询、以及获取锁的 owner 线程

锁的申请增加 try 机制、中断机制、超时机制

lock 就是 api 锁,而 monitor,更强调一种机制,这里面还有 Object 上的 wait-notify 机制,共同组成 monitor 机制,来达到协调多线程运行的目的。

看一张经典图:

java-monitor-mechanism.gif

独占性

一个 monitor ,就好像一幢楼里某一个特殊的房间,这个房间在同一时间内,只能有一个线程进入。

房间里面存放着某些敏感的数据,这些数据需要在并发访问的时候被保护起来,防止出错。

从线程进入房间到离开房间这段时间里,它独占这个房间里的数据。进入这幢楼就等于进入这个 monitor。

进入这个房间就等于请求这个 monitor。

占有这个房间就等于持有这个 monitor。

离开这个房间就等于释放这个 monitor。

离开这幢楼就等于退出这个 monitor。

当某个线程开始访问被保护的数据时,它首先会被放在楼里的一个到达队列(entry-set)里。

如果没有其它线程等待、持有这个锁,那这个线程可以直接请求锁、持有锁、访问保护数据。

完成之后,线程释放锁并且离开大楼。

如果某个线程到达时,monitor 已经被其它线程持有,它必须在达到队列里等上一阵。

当前线程从房间里离开后,达到队列里的线程必须互相竞争,只有一个胜出的线程才能进入房间。

目前为止,monitor 帮助我们实现独占性,确保线程之间不产生错误的影响。

wait-set 还没有发挥作用。

合作性

合作性是指保证线程只在某些特定的条件下才占有房间(持有锁)、访问数据。

例如:生产者-消费者问题。

读线程首先进入 entry-set,发现没有其它线程占有 monitor 时进入房间;但此时恰好 buffer 中没有数据,读线程需要停下来等待。

它释放 monitor,并进入 wait-set 等待。当它下一次请求 monitor 时,读线程需要和来自 entry-set 和 wait-set 的线程竞争,胜出进入房间之后,依旧需要判断。

写线程需要判断 buffer 的大小,如果已经达到 MAX 状态也要停下来,进入 wait-set。

保障合作性同时需要 entry-set 和 wait-set。

资料

<<

<think>嗯,用户想了解Java中synchronizedLock区别,特别是为了面试准备。首先,我需要回忆这两个概念的基本信息。synchronized是Java的关键字,属于内置锁,而Lock是一个接口,属于API层面的锁。接下来,我需要对比它们的特性,比如实现方式、使用方式、功能特性等。 用户提供的引用资料中提到,synchronized基于底层操作系统实现,而Lock是基于Java代码实现的。比如引用4提到synchronized与Java对象头有关,而Lock实现类如ReentrantLock使用AQS(AbstractQueuedSynchronizer)。这点很重要,要区分它们的实现机制。 然后,使用方式上,synchronized可以修饰方法或代码块,自动释放锁,而Lock需要手动获取释放,通常在finally块中释放,避免死锁。例如引用3中的代码示例,synchronized使用简单,但Lock需要显式调用lock()unlock()。 功能特性方面,synchronized不可中断、非公平,而Lock提供了可中断、公平锁选项,还能尝试非阻塞获取锁,如tryLock()。引用5提到Lock的可判断公平性,这也是面试常考的点。 另外,性能方面,早期synchronized性能较差,但后来优化后差距不大。但在高竞争情况下,Lock可能更有优势。不过具体场景需要具体分析。 异常处理方面,synchronized在异常时自动释放锁,而Lock必须手动处理,否则可能导致死锁。引用3中的例子说明了这一点,需要强调在finally中释放锁的重要性。 可能还需要考虑锁的粒度、可重入性等。两者都是可重入的,但Lock提供更灵活的控制。比如读写锁中的ReentrantReadWriteLock,而synchronized无法实现。 用户提供的引用12强调了两者的区别适用场景,面试中可能还会问到如何选择使用哪种锁。需要结合这些点,整理出结构清晰的回答,确保覆盖所有关键区别,并举例说明,帮助记忆。 最后,检查是否有遗漏点,比如等待可中断、条件变量(Condition类)、锁的公平性等。确保回答全面,符合面试准备的深度,同时语言简洁明了,便于用户理解记忆。</think>### Java中synchronized与Lock区别(面试知识点) #### 1. **实现机制** - **synchronized** Java内置关键字,基于JVM底层实现(依赖对象头中的Mark Word监视器锁Monitor)[^4]。锁的获取释放由JVM自动管理,无需手动控制。 ```java public synchronized void method() { /* 同步代码 */ } // 或同步代码块 public void test() { synchronized(this) { /* 同步代码 */ } } ``` - **Lock** 基于Java API实现的接口(如`ReentrantLock`),通过AQS(AbstractQueuedSynchronizer)队列同步器实现[^5]。需要手动调用`lock()``unlock()`方法。 ```java Lock lock = new ReentrantLock(); public void method() { lock.lock(); try { /* 同步代码 */ } finally { lock.unlock(); } // 必须手动释放 } ``` #### 2. **功能特性对比** | 特性 | synchronized | Lock(以ReentrantLock为例) | |--------------------|----------------------------------|------------------------------------| | **锁的获取方式** | 自动获取与释放 | 需手动控制(可能因忘记释放导致死锁) | | **可中断性** | 不可中断 | 支持`lockInterruptibly()`可中断 | | **公平性** | 非公平锁 | 支持公平锁与非公平锁(构造函数指定) | | **条件变量** | 通过`wait()/notify()`实现 | 通过`Condition`对象实现多条件等待 | | **尝试获取锁** | 不支持 | 支持`tryLock()`非阻塞尝试获取 | | **锁的粒度** | 方法或代码块级 | 更灵活(可跨方法控制锁范围) | #### 3. **性能与适用场景** - **synchronized** JDK1.6后优化了偏向锁、轻量级锁等机制,性能与Lock接近。适用于简单的同步场景,如单方法内的线程安全控制。 - **Lock** 提供更细粒度的控制,适用于复杂场景(如尝试获取锁、超时机制、公平锁需求)。例如: ```java if (lock.tryLock(1, TimeUnit.SECONDS)) { // 尝试获取锁,最多等待1秒 try { /* 操作共享资源 */ } finally { lock.unlock(); } } ``` #### 4. **异常处理** - **synchronized**:执行中发生异常会自动释放锁[^3]。 - **Lock**:必须在`finally`中显式释放锁,否则可能导致死锁。 #### 5. **其他区别** - **可重入性**:两者均支持可重入(同一线程可多次获取同一锁)。 - **锁状态查询**:Lock提供`isLocked()`等方法,synchronized无此功能。 --- ### 面试回答模板 > **synchronized与Lock区别** > 1. **实现层面**:synchronized是JVM级关键字,Lock是API级接口。 > 2. **控制方式**:synchronized自动管理锁,Lock需手动获取/释放。 > 3. **功能扩展**:Lock支持可中断、公平锁、多条件变量等高级特性。 > 4. **性能**:高并发下Lock更灵活,但需注意异常处理。 > 5. **适用场景**:简单同步用synchronized,复杂需求(如超时、公平性)用Lock[^1][^2]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值