使用synchronized和Lock对象获取对象锁

本文探讨了在并发环境下使用锁机制解决共享资源冲突的问题,详细介绍了对象锁、synchronized同步块以及Lock对象锁的应用。通过代码示例展示了如何在不同对象或不同方法中实现同步和互斥访问,确保了临界资源的安全使用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在并发环境下,解决共享资源冲突问题时,可以考虑使用锁机制。
[b]1.对象的锁[/b]
所有对象都自动含有单一的锁。
JVM负责跟踪对象被加锁的次数。如果一个对象被解锁,其计数变为0。在任务(线程)第一次给对象加锁的时候,计数变为1。每当这个相同的任务(线程)在此对象上获得锁时,计数会递增。
只有首先获得锁的任务(线程)才能继续获取该对象上的多个锁。
每当任务离开一个synchronized方法,计数递减,当计数为0的时候,锁被完全释放,此时别的任务就可以使用此资源。
[b]2.synchronized同步块[/b]
当使用同步块时,如果方法下的同步块都同步到一个对象上的锁,则所有的任务(线程)只能互斥的进入这些同步块。
Resource1.java演示了三个线程(包括main线程)试图进入某个类的三个不同的方法的同步块中,虽然这些同步块处在不同的方法中,但由于是同步到同一个对象(当前对象 synchronized (this)),所以对它们的方法依然是互斥的。


package cn.java.loak;

import java.util.concurrent.TimeUnit;

public class Resource1 {

public void f(){
System.out.println(Thread.currentThread().getName()+":not synchronized in f()");
synchronized(this){
for(int i=0;i<5; i++){
System.out.println(Thread.currentThread().getName()+":synchronized in f()");
try{
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e){
e.printStackTrace();
}
}
}
}
public void g(){
System.out.println(Thread.currentThread().getName()+":not synchronized in g()");
synchronized(this){
for(int i=0;i<5;i++){
System.out.println(Thread.currentThread().getName()+":synchronized in g()");
try{
TimeUnit.SECONDS.sleep(3);
}catch (InterruptedException e){
e.printStackTrace();
}
}
}
}
public void h(){
System.out.println(Thread.currentThread().getName()+":not synchronized in h()");
synchronized(this){
for(int i=0;i<5;i++){
System.out.println(Thread.currentThread().getName()+":synchronized in h()");
try{
TimeUnit.SECONDS.sleep(3);
} catch(InterruptedException e){
e.printStackTrace();
}
}
}
}

public static void main(String [] args){
final Resource1 rs=new Resource1();
new Thread(){
public void run(){
rs.f();
}
}.start();
new Thread(){
public void run(){
rs.g();
}
}.start();

rs.h();
}
}

运行结果:
Thread-0:not synchronized in f()
Thread-0:synchronized in f()
main:not synchronized in h()
Thread-1:not synchronized in g()
Thread-0:synchronized in f()
Thread-0:synchronized in f()
Thread-0:synchronized in f()
Thread-0:synchronized in f()
Thread-1:synchronized in g()
Thread-1:synchronized in g()
Thread-1:synchronized in g()
Thread-1:synchronized in g()
Thread-1:synchronized in g()
main:synchronized in h()
main:synchronized in h()
main:synchronized in h()
main:synchronized in h()
main:synchronized in h()

[b]2.2 同步到多个对象锁[/b]
Resource2.java演示了三个线程(包括main线程)试图进入某个类的三个不同的方法的同步块中,这些同步块处在不同的方法中,并且是同步到三个不同的对象(synchronized (this),synchronized (syncObject1),synchronized (syncObject2)),所以对它们的方法中的临界资源访问是独立的。

package cn.java.loak;

import java.util.concurrent.TimeUnit;

public class Resource2 {
private Object syncObject1=new Object();
private Object syncObject2=new Object();

public void f(){
System.out.println(Thread.currentThread().getName()+":not synchronized in f()");
synchronized(this){
for(int i=0;i<5;i++){
System.out.println(Thread.currentThread().getName()+":synchronized in f()");
try{
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e){
e.printStackTrace();
}
}
}
}

public void g(){
System.out.println(Thread.currentThread().getName()+":not synchronized in g()");
synchronized (syncObject1){
for(int i=0;i<5;i++){
System.out.println(Thread.currentThread().getName()+":synchronized in g()");
try{
TimeUnit.SECONDS.sleep(3);
} catch(InterruptedException e){
e.printStackTrace();
}
}
}
}

public void h(){
System.out.println(Thread.currentThread().getName()+":not synchronized in h()");
synchronized(syncObject2){
for(int i=0;i<5;i++){
System.out.println(Thread.currentThread().getName()+":synchronized in h()");
try{
TimeUnit.SECONDS.sleep(3);

} catch(InterruptedException e){
e.printStackTrace();
}
}
}
}
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
final Resource2 rs=new Resource2();

new Thread(){
public void run(){
rs.f();
}
}.start();

new Thread(){
public void run(){
rs.g();

}
}.start();

rs.h();
}

}


运行结果
Thread-0:not synchronized in f()
Thread-0:synchronized in f()
main:not synchronized in h()
main:synchronized in h()
Thread-1:not synchronized in g()
Thread-1:synchronized in g()
Thread-0:synchronized in f()
main:synchronized in h()
Thread-1:synchronized in g()
Thread-0:synchronized in f()
main:synchronized in h()
Thread-1:synchronized in g()
Thread-0:synchronized in f()
main:synchronized in h()
Thread-1:synchronized in g()
Thread-0:synchronized in f()
main:synchronized in h()
Thread-1:synchronized in g()

[b]3.Lock对象锁[/b]
除了使用synchronized外,还可以使用Lock对象来创建临界区。Resource3.java的演示效果同Resource1.java;Resource4.java的演示效果同Resource2.java。

package cn.java.loak;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class Resource3 {
private Lock lock = new ReentrantLock();

public void f(){
System.out.println(Thread.currentThread().getName()+":not synchronized in f()");
lock.lock();
try{
for (int i=0;i<5;i++){
System.out.println(Thread.currentThread().getName()+"synchronized in f()");
try{
TimeUnit.SECONDS.sleep(3);
}catch(InterruptedException e){
e.printStackTrace();
}
}
}finally{
lock.unlock();
}
}

public void g(){
System.out.println(Thread.currentThread().getName()+":not synchronized in g()");
lock.lock();
try{
for (int i=0;i<5;i++){
System.out.println(Thread.currentThread().getName()+"synchronized in g()");
try{
TimeUnit.SECONDS.sleep(3);
}catch(InterruptedException e){
e.printStackTrace();
}
}
}finally{
lock.unlock();
}
}
public void h(){
System.out.println(Thread.currentThread().getName()+":not synchronized in h()");
lock.lock();
try{
for (int i=0;i<5;i++){
System.out.println(Thread.currentThread().getName()+"synchronized in h()");
try{
TimeUnit.SECONDS.sleep(3);
}catch(InterruptedException e){
e.printStackTrace();
}
}
}finally{
lock.unlock();
}
}

public static void main(String[] args){
final Resource3 rs=new Resource3();

new Thread(){
public void run(){
rs.f();
}
}.start();

new Thread(){
public void run(){
rs.g();
}
}.start();

rs.h();
}
}


运行结果
Thread-0:not synchronized in f()
Thread-0synchronized in f()
main:not synchronized in h()
Thread-1:not synchronized in g()
Thread-0synchronized in f()
Thread-0synchronized in f()
Thread-0synchronized in f()
Thread-0synchronized in f()
mainsynchronized in h()
mainsynchronized in h()
mainsynchronized in h()
mainsynchronized in h()
mainsynchronized in h()
Thread-1synchronized in g()
Thread-1synchronized in g()
Thread-1synchronized in g()
Thread-1synchronized in g()
Thread-1synchronized in g()


package cn.java.loak;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class Resource4 {
private Lock lock1=new ReentrantLock();
private Lock lock2=new ReentrantLock();
private Lock lock3=new ReentrantLock();

public void f(){
System.out.println(Thread.currentThread().getName()+":not synchronized in f()");
lock1.lock();
try{
for(int i=0;i<5;i++){
System.out.println(Thread.currentThread().getName()+":synchronized in f()");
try{
TimeUnit.SECONDS.sleep(3);
}catch(InterruptedException e){
e.printStackTrace();
}

}
}finally{
lock1.unlock();
}
}
public void g(){
System.out.println(Thread.currentThread().getName()+":not synchronized in g()");
lock2.lock();
try{
for(int i=0;i<5;i++){
System.out.println(Thread.currentThread().getName()+":synchronized in g()");
try{
TimeUnit.SECONDS.sleep(3);
}catch(InterruptedException e){
e.printStackTrace();
}

}
}finally{
lock2.unlock();
}
}
public void h(){
System.out.println(Thread.currentThread().getName()+":not synchronized in h()");
lock3.lock();
try{
for(int i=0;i<5;i++){
System.out.println(Thread.currentThread().getName()+":synchronized in h()");
try{
TimeUnit.SECONDS.sleep(3);
}catch(InterruptedException e){
e.printStackTrace();
}

}
}finally{
lock3.unlock();
}
}
public static void main(String[] args){
final Resource4 rs=new Resource4();

new Thread(){
public void run(){
rs.f();
}
}.start();

new Thread(){
public void run(){
rs.g();
}
}.start();

rs.h();
}
}

运行结果
Thread-0:not synchronized in f()
Thread-0:synchronized in f()
main:not synchronized in h()
main:synchronized in h()
Thread-1:not synchronized in g()
Thread-1:synchronized in g()
Thread-0:synchronized in f()
main:synchronized in h()
Thread-1:synchronized in g()
Thread-0:synchronized in f()
main:synchronized in h()
Thread-1:synchronized in g()
Thread-0:synchronized in f()
main:synchronized in h()
Thread-1:synchronized in g()
Thread-0:synchronized in f()
main:synchronized in h()
Thread-1:synchronized in g()
<think>嗯,用户要求我参考站内引用来介绍JavasynchronizedLock锁的区别及使用场景。用户在上次对话中已经详细询问过Java锁机制,这次聚焦在两种核心锁的对比上。 从引用内容看,用户提供的资料已经相当全面。引用[1][2][4][5]都直接对比了synchronizedLock的特性,尤其是引用[4]的对比表格非常清晰。我需要整合这些信息,同时结合自己掌握的Java并发知识来组织回答。 用户可能正在准备面试或设计并发程序,需要明确的决策依据。回答应该突出实际场景的选择建议,而不仅是理论差异。注意到引用[5]特别提到“synchronized适合低并发,ReentrantLock适合高并发”这个关键点,这应该是性能维度的核心结论。 在结构上,考虑先展示差异矩阵(参考引用[4]的表格形式),然后分别说明适用场景。对于使用示例,准备用代码片段展示两种锁的基本用法,特别是Lock必须配合try-finally释放锁这个易错点(引用[2][4]都强调过)。 用户可能还会关心锁升级机制(引用[2]提到synchronized的偏向锁优化)死锁处理(引用[4]提到Lock可中断),这些都需要包含在回答中。最后考虑用流程图形式展示锁选择策略,帮助用户快速决策。</think>以下是Java中`synchronized`与`Lock`锁的详细对比及使用场景分析,结合核心引用内容整理: --- ### 一、核心区别对比 | **特性** | **synchronized** | **Lock (ReentrantLock)** | |------------------------|------------------------------------------|-----------------------------------------| | **实现层级** | JVM层面关键字(内置) | Java API接口(`java.util.concurrent.locks`) | | **锁获取/释放** | 自动获取释放(代码块结束或异常时) | 必须手动调用`lock()``unlock()`[^4] | | **可中断性** | 等待中不可中断 | 支持`lockInterruptibly()`响应中断[^2][^5] | | **公平性** | 仅支持非公平锁 | 可通过构造参数指定公平/非公平锁[^2][^4] | | **锁状态检测** | 无法判断锁状态 | 可通过`tryLock()`检测锁是否被占用[^4][^5] | | **锁绑定条件** | 仅支持单一等待队列 | 支持绑定多个`Condition`实现精准唤醒[^1][^3] | | **性能倾向** | 低竞争场景效率高(JVM自动优化锁升级)[^5] | 高竞争场景更优(减少线程挂起开销)[^1][^5] | | **锁粒度** | 方法级或代码块级 | 可灵活控制锁范围(如跨方法加锁)[^2] | --- ### 二、使用场景分析 #### 1. **优先选择 `synchronized` 的场景** - **简单同步需求**:如单方法内的临界区保护 ```java public synchronized void add() { count++; // 自动加锁/释放锁 } ``` - **低线程竞争环境**:JVM的锁升级(偏向锁→轻量级锁)可减少开销[^5] - **避免死锁风险**:自动释放锁机制降低编码失误概率[^4] #### 2. **优先选择 `Lock` 的场景** - **需要高级功能**: - 尝试获取锁(避免死锁): ```java if (lock.tryLock(1, TimeUnit.SECONDS)) { // 超时等待 try { /* 操作共享资源 */ } finally { lock.unlock(); } } ``` - 公平性要求:`new ReentrantLock(true)`[^4] - 多条件唤醒: ```java Condition condition = lock.newCondition(); condition.await(); // 精准唤醒特定线程 condition.signal(); ``` - **高并发写场景**:通过减少线程阻塞提升吞吐量[^5] - **跨方法锁控制**: ```java void methodA() { lock.lock(); try { ... } finally { /* 不在A方法释放锁 */ } } void methodB() { try { ... } finally { lock.unlock(); } // 在B方法释放锁 } ``` --- ### 三、底层原理差异 | **维度** | **synchronized** | **ReentrantLock** | |-------------------|--------------------------------------------------|-------------------------------------------| | **实现机制** | 对象头Mark Word + Monitor锁(JVM底层实现)[^2] | 基于AQS(AbstractQueuedSynchronizer)[^3] | | **锁升级路径** | 无锁 → 偏向锁 → 轻量级锁 → 重量级锁[^2] | 无锁升级概念 | | **重入实现** | 通过计数器递归实现[^3] | 同步状态state计数实现[^3] | > ⚠️ **注意**: > - `synchronized`在JDK6后引入锁升级,但**重量级锁不可逆**; > - `Lock`需严格在`finally`中释放锁,否则会导致死锁[^4][^5] --- ### 四、典型代码示例 #### 1. `ReentrantReadWriteLock` 读写分离(引用[4]) ```java ReadWriteLock rwLock = new ReentrantReadWriteLock(); // 读操作(共享锁) rwLock.readLock().lock(); try { // 多线程并发读 } finally { rwLock.readLock().unlock(); } // 写操作(独占锁) rwLock.writeLock().lock(); try { // 单线程写 } finally { rwLock.writeLock().unlock(); } ``` #### 2. `Lock` 响应中断(引用[5]) ```java Lock lock = new ReentrantLock(); try { lock.lockInterruptibly(); // 可被其他线程中断 try { /* 临界区 */ } finally { lock.unlock(); } } catch (InterruptedException e) { Thread.currentThread().interrupt(); // 恢复中断状态 } ``` --- ### 五、选型决策流程图 ```mermaid graph TD A[需要同步?] --> B{竞争强度} B -->|低竞争| C[synchronized] B -->|高竞争| D{需高级功能?} D -->|是| E[ReentrantLock] D -->|否| C E --> F[需要读写分离?] F -->|是| G[ReentrantReadWriteLock] F -->|否| E ``` > 📌 **总结原则**: > 1. **简单优先**:无特殊需求时首选`synchronized` > 2. **灵活控制**:需超时、可中断、公平锁时用`Lock` > 3. **读写分离**:读多写少场景用`ReentrantReadWriteLock`[^4] --- ### 参考资料 [^1]: Java锁:Locksynchronized的全面对比 [^2]: SynchronizedLock的实现原理及使用场景 [^3]: synchronizedLock深度对比及高级用法 [^4]: synchronizedLock的区别使用示例 [^5]: synchronizedLock锁的面试题解析
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值