Synchronized
Synchronized基本描述
·对于普通同步方法,锁是当前实例对象。
·对于静态同步方法,锁是当前类的Class对象。
·对于同步方法块,锁是Synchonized括号里配置的对象。
JVM基于进入和退出Monitor对象来实现方法同步和代码块同步,但两者的实现细节不一样。代码块同步是使用monitorenter和monitorexit指令实现的,而方法同步是使用另外一种方式实现的,synchronized
修饰的方法并没有 monitorenter
指令和 monitorexit
指令,取得代之的是 ACC_SYNCHRONIZED
标识
monitorenter指令是在编译后插入到同步代码块的开始位置,而monitorexit是插入到方法结束处和异常处
任何对象都有一个monitor与之关联,当一个monitor被持有后,它将处于锁定状态。线程执行到monitorenter指令时,将会尝试获取对象所对应的monitor的所有权,即尝试获得对象的锁。
// 锁方法
public synchronized void add(){
i++;
}
public synchronized void add();
descriptor: ()V
flags: (0x0021) ACC_PUBLIC, ACC_SYNCHRONIZED
Code:
stack=3, locals=1, args_size=1
0: aload_0
1: dup
2: getfield #2 // Field i:I
5: iconst_1
6: iadd
7: putfield #2 // Field i:I
10: return
// 锁代码块
public void add() {
synchronized (this) {
i++;
}
}
public void add();
Code:
0: aload_0
1: dup
2: astore_1
3: monitorenter // synchronized关键字的入口
4: getstatic #2 // Field i:I
7: iconst_1
8: iadd
9: putstatic #2 // Field i:I
12: aload_1
13: monitorexit // 正常程序执行synchronized关键字的出口
14: goto 22
17: astore_2
18: aload_1
19: monitorexit // 抛异常时synchronized关键字的出口
20: aload_2
21: athrow
22: return
Java对象头
synchronized用的锁是存在Java对象头里的
不同类型对象,对象头的字宽说明,在32位虚拟机中,1字宽等于4字节,即32bit
- 数组类型:3字宽
- 非数组:2字宽
对象头组成
- Mark Word(1字宽)
- 对象数据类型指针(1字宽)
- 数组长度(这就是数据多的一个字宽的用处)
Mark Word
无锁状态
运行期间
口诀:25+4+1+2,2️⃣ 5️⃣法则:2锁,5针
口诀:00轻、10重、11GC、01偏
特殊案例分析
1.synchronized(this),锁的对象是this,是类的实例。
2.synchronized(object),锁的对象是object。
class STest{
public void print(){
synchronized (this){
System.out.println("xxxx");
}
}
}
public class SynchronizeMain {
public static void main(String[] args) throws InterruptedException {
STest sTest = new STest();
// Thread 1
Thread t1 = new Thread(() -> {
sTest.print();
});
// Thread 2
Thread t2 = new Thread(() -> {
try {
synchronized (sTest){
while (true);
}
} catch (Exception e) {
System.out.println("Exception="+e.getMessage());
}
});
// 抢占了 sTest 锁,属于同步块锁,锁的是 sTest 对象
t2.start();
// sTest.print()永远无法执行
t1.start();
}
}
如果第一种方式用锁,如果使用这种方式,一旦锁对象(实例)被别人获取,那么线程将会被挂起,这就是说,当实例方法被别的线程锁住,就有可能造成正常锁代码块无法执行。
如果第二种方式用锁,除非都调用方法块内的方法,否则互不影响。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!