synchronized (obj) 锁住不同的对象的话

本文通过一个简单的Java示例,展示了如何使用synchronized关键字实现线程间的同步操作,并探讨了当同步块锁定不同对象时,线程如何避免相互阻塞。
部署运行你感兴趣的模型镜像

 

Obj 

package com.james.thread.sync;

public class SyncObject {

	byte[] lock1 = new byte[0];
	byte[] lock2 = new byte[0];

	int i = 1;

	public int minus() {
		try {
		
		synchronized (lock1) {
			System.out.println("minus in");
			Thread.currentThread().sleep(300);
				i--;
				System.out.println("minus " + i);
			
			
		}
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		return i;
	}

	public int add() {
		
		synchronized (lock2) {
			try {
				System.out.println("add in");
				Thread.currentThread().sleep(5);
				i++;
				System.out.println("add " + i);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			return i;
		}

	}
	
	public synchronized int minus2() {
			i--;
			System.out.println("minus "+ i);
			return i;

	}

	public synchronized int add2() {
			i++;
			System.out.println("add "+ i);
			return i;

	}

}

 

Test

package com.james.thread.sync;

public class Test {

	public static void main(String[] args) throws InterruptedException {
		SyncObject obj = new SyncObject ();
		Thread t =null;
		for(int i =1;i<3;i++){
			t = new Thread(new TestThread (i,obj));
			t.start();
		}
//		Thread.currentThread().sleep(500);
//		System.out.println(obj.i);
	}

	static class TestThread implements Runnable {
		private int flag = 100;
		private SyncObject obj;
		public TestThread(int flag,SyncObject obj){
			this.flag = flag;
			this.obj = obj;
		}
		public void run (){
			if(flag %2 == 0){
				obj.add();
			}else{
				obj.minus();
			}
		}
	}
}

 

输出

minus in
add in
add 2
minus 1

 

说明 synchronized块锁住不同对象的时候,同步块里是不会阻塞的。

 

 

您可能感兴趣的与本文相关的镜像

Stable-Diffusion-3.5

Stable-Diffusion-3.5

图片生成
Stable-Diffusion

Stable Diffusion 3.5 (SD 3.5) 是由 Stability AI 推出的新一代文本到图像生成模型,相比 3.0 版本,它提升了图像质量、运行速度和硬件效率

<think>我们正在讨论Java中的synchronized关键字如何作用于隐式对象。根据引用[1][2][3][4],synchronized关键字通过获取对象的监视器(monitor)来实现同步,而这个对象可以是隐式的(即不显式指定,而是由编译器根据上下文确定)。下面我将详细解释synchronized如何作用于隐式对象。 ### 1. **synchronized作用于实例方法(隐式对象为this)** - 当`synchronized`修饰实例方法时,对象是**当前实例对象**(即`this`),这是隐式指定的。 - 示例: ```java public synchronized void method() { // 临界区代码 } ``` - 等效于显式锁住`this`: ```java public void method() { synchronized (this) { // 显式使用this作为对象 // 临界区代码 } } ``` - **原理**:线程进入方法前自动获取当前实例的,退出时自动释放[^1][^3]。 - **影响**:多个线程访问同一个对象的该方法时会发生互斥;但访问不同对象的该方法时不会互斥(因为对象不同)[^3]。 ### 2. **synchronized作用于静态方法(隐式对象为Class对象)** - 当`synchronized`修饰静态方法时,对象是**当前类的Class对象**(如`MyClass.class`),这也是隐式指定的。 - 示例: ```java public static synchronized void staticMethod() { // 临界区代码 } ``` - 等效于显式锁住对象: ```java public static void staticMethod() { synchronized (MyClass.class) { // 显式使用Class对象 // 临界区代码 } } ``` - **原理**:静态方法属于类而非实例,因此对象是类对象(在JVM中唯一)[^1][^3]。 - **影响**:所有线程调用该静态方法时都会互斥(无论实例是否相同)[^3]。 ### 3. **为什么称为“隐式对象”?** - **无需显式声明**:在上述两种方法中,开发者无需在代码中显式写出对象(如`this`或`MyClass.class`),而是由编译器根据`synchronized`的修饰位置自动推断[^1][^3]。 - **简化代码**:这种隐式机制减少了模板代码,但牺牲了灵活性(例如无法选择非this的对象)[^2]。 ### 4. **底层实现与隐式的获取** - **监视器(Monitor)**:每个Java对象都关联一个Monitor,隐式的获取即对应Monitor的进入(`monitorenter`指令),释放对应退出(`monitorexit`指令)[^1][^4]。 - **可重入性**:隐式是可重入的(Reentrant)。例如: ```java public synchronized void methodA() { methodB(); // 调用同一对象的另一个synchronized方法 } public synchronized void methodB() {} ``` 线程在`methodA`中已持有`this`,调用`methodB`时可再次获取同一[^4]。 ### 5. **隐式的注意事项** - **粒度问题**:隐式对象(如`this`或类对象)通常范围较大,可能造成不必要的阻塞。例如: - 锁住整个实例对象(`this`)会阻塞该对象所有`synchronized`实例方法的并发访问[^3]。 - 锁住对象会阻塞所有静态`synchronized`方法的访问。 - **替代方案**:若需细粒度控制,可显式指定对象(如私有字段): ```java private final Object lock = new Object(); public void method() { synchronized (lock) { // 仅锁住特定代码段 // 临界区 } } ``` ### 总结 Java中的`synchronized`关键字通过隐式对象定实现同步: 1. **实例方法** → 隐式对象为`this`(当前实例)。 2. **静态方法** → 隐式对象为类对象(如`MyClass.class`)。 这种机制简化了同步代码的编写,但开发者需注意粒度和性能影响。在需要更高灵活性时,建议使用显式对象或`java.util.concurrent`包中的工具[^2][^3]。 §§相关问题§§ 1. synchronized隐式与显式(如ReentrantLock)有何性能差异? 2. 如何选择synchronized的隐式与显式? 3. synchronized隐式在继承体系中的行为是怎样的?</think>### Javasynchronized关键字如何作用于隐式对象Java中,`synchronized`关键字通过**隐式对象**实现线程同步。这种机制由JVM自动管理,开发者无需显式创建对象。以下是详细分析(结合引用内容): #### 1. **隐式的基本原理 - **监视器(Monitor)**:每个Java对象都内置一个监视器(隐式),当线程进入`synchronized`区域时,JVM自动获取该对象的监视器[^1]。 - **的固化**:`synchronized`隐式固化的获取和释放流程(先获取→执行→释放),简化同步管理[^2]。 - **可重入性**:同一线程可多次获取同一对象的隐式(重入),避免自我死[^4]。 #### 2. **隐式的三种应用场景 (以`MyClass`类为例) | 使用方式 | 隐式对象 | 作用范围 | 示例代码片段 | |---------------------------|-------------------|-----------------------------|--------------------------------| | **实例方法** | 当前实例(`this`) | 同一对象的所有同步方法 | ```java\npublic synchronized void methodA() {...}\n``` [^3] | | **静态方法** | 类对象(`MyClass.class`) | 该类的所有实例 | ```java\npublic static synchronized void staticMethod() {...}\n``` [^3] | | **代码块(无显式对象)** | 当前实例(`this`) | 同一对象同步代码块 | ```java\nsynchronized(this) {...}\n``` [^3] | #### 3. **隐式的工作机制 ```mermaid sequenceDiagram participant ThreadA participant ObjectLock participant ThreadB ThreadA->>ObjectLock: 尝试获取隐式 activate ObjectLock ObjectLock-->>ThreadA: 授予 ThreadA->>ThreadA: 执行同步代码 ThreadA->>ObjectLock: 释放 deactivate ObjectLock ThreadB->>ObjectLock: 尝试获取(等待) ObjectLock-->>ThreadB: 阻塞直到可用 ``` 1. **获取**:线程进入`synchronized`区域时,JVM自动尝试获取对象的隐式。 2. **持有**:若可用,线程持有并执行同步代码;若被占用,线程进入阻塞状态。 3. **释放**:线程退出同步区域(正常或异常)时,JVM自动释放[^1][^2]。 #### 4. **关键特性 1. **对象级互斥**: - 锁住实例对象时:阻止其他线程访问**同一对象**的任何`synchronized`方法[^3]。 - 锁住对象时:阻止其他线程访问**该类的所有实例**的静态同步方法[^3]。 2. **不同对象互不干扰**: ```java MyClass obj1 = new MyClass(); MyClass obj2 = new MyClass(); // 线程A访问obj1的同步方法,不影响线程B访问obj2的同步方法 ``` 3. **升级优化**: - JVM会根据竞争情况,将隐式从**偏向→轻量级→重量级**逐步升级[^4]。 - 例如:无竞争时使用偏向(低开销),高竞争时升级为重量级(减少CPU空转)。 #### 5. **注意事项 - **避免粒度问题**:隐式默认定整个对象,可能造成不必要的阻塞。建议: ```java // 细粒度优化 private final Object segmentLock = new Object(); public void optimizedMethod() { // 非同步代码... synchronized(segmentLock) { // 仅定必要部分 // 临界区代码 } } ``` - **不可中断性**:线程获取隐式时无法被中断(需用`ReentrantLock`实现可中断)[^2]。 ### 总结 Java的`synchronized`通过**对象的隐式监视器**实现同步: - 实例方法 → `this` - 静态方法 → `Class`对象 - 未指定对象代码块`this` 这种机制简化了线程安全代码的编写,但开发者需注意粒度和性能影响[^1][^3][^4]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值