synchronized的解析
synchronized是使用对象作为mutex的,按照之前的介绍,相关信息存储在mark字段中,具体参考前面的描述。
这里分析一种简单的场景,2个线程基于同一个对象进行同步,跟踪下具体的sys call。
源码如下:
public class SynchronizedViewDemo {
public static void main(String[] args) throws IOException, InterruptedException {
final DataEntity data = new DataEntity();
data .setDataId(0x01020304);
ExecutorService service = Executors.newFixedThreadPool(1);
service .submit( new Runnable() {
@Override
public void run() {
System. out .println("pool-prelock" );
synchronized (data ) {
System. out .println("pool-lock" );
try {
Thread. sleep(5000);
} catch (InterruptedException e ) {
}
}
System. out .println("pool-postlock" );
}
});
System. out .println("main-prelock" );
synchronized (data ) {
System. out .println("main-lock" );
Thread. sleep(5000);
}
System. out .println("main-postlock" );
}
}
class DataEntity {
private int dataId ;
public int getDataId() {
return dataId ;
}
public void setDataId( int dataId) {
this .dataId = dataId;
}
}
运行后的结果如下:
main-prelock
main-lock
pool-prelock
main-postlock
pool-lock
pool-postlock
我们通过sys call的日志,根据我们的输出关键字分析日志:
main线程先获得lock,sleep了5秒,然后退出:
10218 03:16:41.470827 write(1, "main-prelock", 12) = 12 <0.000023> --从这里开始分析
10218 03:16:41.470930 write(1, "\n", 1) = 1 <0.000011>
10218 03:16:41.470987 write(1, "main-lock", 9) = 9 <0.000012> --已经进入lock同步区
10218 03:16:41.474623 write(1, "\n", 1 <unfinished ...>
10218 03:16:41.475210 <... write resumed> ) = 1 <0.000548>
10218 03:16:41.475613 futex(0x7f03b800ab54, FUTEX_WAIT_BITSET_PRIVATE, 1, {95182, 291960491}, ffffffff <unfinished ...> --通过futex进行sleep 5秒
10218 03:16:46.475729 <... futex resumed> ) = -1 ETIMEDOUT (Connection timed out) <5.000095> --futex超时唤醒
10218 03:16:46.475771 futex(0x7f03b800ab28, FUTEX_WAKE_PRIVATE, 1 <unfinished ...>
10218 03:16:46.475817 <... futex resumed> ) = 0 <0.000041>
10218 03:16:46.475904 futex(0x7f03b80cd454, FUTEX_WAKE_OP_PRIVATE, 1, 1, 0x7f03b80cd450, {FUTEX_OP_SET, 0, FUTEX_OP_CMP_GT, 1} <unfinished ...> --唤醒锁上的等待线程
10218 03:16:46.475964 <... futex resumed> ) = 1 <0.000044>
--这里有2个futex sys call,我们分别在pool线程的日志里找下,结果第2个是WAKE pool线程
10218 03:16:46.476092 write(1, "main-postlock", 13 <unfinished ...>
pool线程先等待锁, 获得锁后,sleep5秒,然后退出:
我们看到0x7f03b80cd454的futex调用,全部超时,直到最后
10229 03:16:41.476693 write(1, "pool-prelock", 12) = 12 <0.000080> --从这里开始分析
10229 03:16:41.476855 write(1, "\n", 1) = 1 <0.000057>
10229 03:16:41.477086 futex(0x7f03b80cd454, FUTEX_WAIT_BITSET_PRIVATE, 1, {95177, 294482142}, ffffffff) = -1 ETIMEDOUT (Connection timed out) <0.001353>
10229 03:16:41.478567 futex(0x7f03b80cd428, FUTEX_WAKE_PRIVATE, 1) = 0 <0.000046>
10229 03:16:41.478728 futex(0x7f03b80cd454, FUTEX_WAIT_BITSET_PRIVATE, 1, {95177, 303136342}, ffffffff) = -1 ETIMEDOUT (Connection timed out) <0.009694>
10229 03:16:41.488531 futex(0x7f03b80cd428, FUTEX_WAKE_PRIVATE, 1) = 0 <0.000007>
10229 03:16:41.488607 futex(0x7f03b80cd454, FUTEX_WAIT_BITSET_PRIVATE, 1, {95177, 369037136}, ffffffff <unfinished ...>
10229 03:16:41.555049 <... futex resumed> ) = -1 ETIMEDOUT (Connection timed out) <0.066414>
10229 03:16:41.555263 futex(0x7f03b80cd428, FUTEX_WAKE_PRIVATE, 1) = 0 <0.000014>
10229 03:16:41.555439 futex(0x7f03b80cd454, FUTEX_WAIT_BITSET_PRIVATE, 1, {95177, 883860022}, ffffffff <unfinished ...>
10229 03:16:42.069002 <... futex resumed> ) = -1 ETIMEDOUT (Connection timed out) <0.513513>
10229 03:16:42.069590 futex(0x7f03b80cd428, FUTEX_WAKE_PRIVATE, 1) = 0 <0.000487>
10229 03:16:42.070205 futex(0x7f03b80cd454, FUTEX_WAIT_BITSET_PRIVATE, 1, {95178, 886629133}, ffffffff <unfinished ...>
10229 03:16:43.078648 <... futex resumed> ) = -1 ETIMEDOUT (Connection timed out) <1.008402>
10229 03:16:43.092281 futex(0x7f03b80cd428, FUTEX_WAKE_PRIVATE, 1) = 0 <0.000007>
10229 03:16:43.092372 futex(0x7f03b80cd454, FUTEX_WAIT_BITSET_PRIVATE, 1, {95179, 908802560}, ffffffff <unfinished ...>
10229 03:16:44.093036 <... futex resumed> ) = -1 ETIMEDOUT (Connection timed out) <1.000598>
10229 03:16:44.095215 futex(0x7f03b80cd428, FUTEX_WAKE_PRIVATE, 1) = 0 <0.000078>
10229 03:16:44.095480 futex(0x7f03b80cd454, FUTEX_WAIT_BITSET_PRIVATE, 1, {95180, 911841327}, ffffffff <unfinished ...>
10229 03:16:45.095663 <... futex resumed> ) = -1 ETIMEDOUT (Connection timed out) <1.000151>
10229 03:16:45.096189 futex(0x7f03b80cd428, FUTEX_WAKE_PRIVATE, 1) = 0 <0.000716>
10229 03:16:45.097337 futex(0x7f03b80cd454, FUTEX_WAIT_BITSET_PRIVATE, 1, {95181, 913470282}, ffffffff <unfinished ...>
10229 03:16:46.097767 <... futex resumed> ) = -1 ETIMEDOUT (Connection timed out) <1.000385>
10229 03:16:46.097879 futex(0x7f03b80cd428, FUTEX_WAKE_PRIVATE, 1) = 0 <0.000038>
10229 03:16:46.098083 futex(0x7f03b80cd454, FUTEX_WAIT_BITSET_PRIVATE, 1, {95182, 914473898}, ffffffff <unfinished ...>
10229 03:16:46.475933 <... futex resumed> ) = 0 <0.377816> --这里被唤醒了。
10229 03:16:46.476055 futex(0x7f03b80cd428, FUTEX_WAKE_PRIVATE, 1 <unfinished ...>
10229 03:16:46.476177 <... futex resumed> ) = 0 <0.000110>
10229 03:16:46.476352 write(1, "pool-lock", 9 <unfinished ...>
这里说明2个问题:
1. synchronized的heavyweight lock的wait和wake是通过futex实现的
2. sleep是通过futex实现的
分享到:
相关推荐
java并发编程实践笔记java并发编程实践笔记java并发编程实践笔记java并发编程实践笔记
Java并发编程学习笔记
java并发编程实战pdf学习笔记 总结了重要的知识点
Java并发编程系列心得笔记,可以参考,欢迎共同交流学习
java并发编程的艺术读书笔记根据章节整理的核心内容,便于自己理解
读书笔记-Java并发编程实战-基础篇
目前,在Java并发编程方面论述系统、内容详实的中文资料很少。本文是作者在实际工作中经验总结,部分内容来自《Java Concurrency In Practice》。涵盖了Java并发编程所需掌握的大部分知识,且实例丰富通俗易懂。读完...
java并发编程学习笔记,很详细的资料
《Java并发编程的艺术》笔记 第一章 并发编程的挑战 第二章 Java并发机制的底层实现原理 volatile的两条实现原则: 1. Lock前缀指令会引起处理器缓存回写到内存 2. 一个处理器的缓存回写到内存会导致其他...
java并发编程实践笔记资料.pdf
《java并发编程实战》读书笔记-第3章-对象的共享,脑图形式,使用xmind8制作 包括可见性、发布与逸出、线程封闭、不可变性、安全发布等内容
java并发编程笔记
《Java并发编程实战》个人读书笔记,非常详细: 1 简介 2 线程安全性 3 对象的共享 4 对象的组合 5 基础构建模块 6 任务执行 7 取消与关闭 8 线程池的使用 9 图形用户界面应用程序 10 避免活跃性危险 11 性能与可...
Java并发编程与高并发解决方案-学习笔记-www.itmuch.com
绝对的好东西,亲测,认真读读绝对大有裨益,欢迎下载!
Java并发编程学习笔记.
《java并发编程实战》读书笔记-第2章-线程安全性,脑图形式,使用xmind8制作 包括引言、线程安全性定义、原子性、加锁机制、使用锁保护状态、活跃性与性能等内容
《java并发编程实战》读书笔记-第3章-对象的共享,脑图形式,使用xmind8制作 包括线程安全类设计、实例封闭、线程安全性委托、现有线程安全类中添加功能和文档化同步策略等内容
《java并发编程实战》读书笔记-第3章-对象的共享,脑图形式,使用xmind8制作 包括同步容器类、并发容器类、阻塞队列和生产者消费者模式、阻塞和中断方法、同步工具类。最后是构建高效且可伸缩的结果缓存