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并发编程的核心概念。 1. **线程和进程的区别** - **线程** 是程序执行的最小单位,一个进程中可以有多个线程同时执行,共享同一块内存空间,通信...
这本"Java并发编程学习笔记"可能是作者在深入研究Java并发特性、工具和最佳实践过程中积累的心得体会。下面,我们将根据这个主题,探讨一些关键的Java并发编程知识点。 1. **线程与进程**:在多任务环境中,线程是...
Java并发编程系列心得笔记,可以参考,欢迎共同交流学习
### Java并发编程实践笔记知识点详解 #### 一、保证线程安全的方法 1. **不要跨线程访问共享变量:** 当多个线程共享某个变量时,若其中一个线程修改了该变量,其他线程若没有正确同步,则可能读取到错误的数据。...
java并发编程的艺术读书笔记根据章节整理的核心内容,便于自己理解
Java并发编程是Java开发中必不可少的一部分,涉及到多线程、同步机制、线程池以及并发工具类等多个核心知识点。以下是对这些主题的详细说明: 1. **线程安全与锁 Synchronized 底层实现原理**: 线程安全是指在多...
读书笔记:Java并发编程之美笔记
### Java并发编程知识点详解 #### 一、线程状态与管理 在Java中,线程具有多种状态,这些状态的变化反映了线程在其生命周期中的不同阶段。理解这些状态及其转换对于编写高效、健壮的并发程序至关重要。 - **NEW**...
《Java并发编程的艺术》笔记 第一章 并发编程的挑战 第二章 Java并发机制的底层实现原理 volatile的两条实现原则: 1. Lock前缀指令会引起处理器缓存回写到内存 2. 一个处理器的缓存回写到内存会导致其他...
《java并发编程实战》读书笔记-第3章-对象的共享,脑图形式,使用xmind8制作 包括可见性、发布与逸出、线程封闭、不可变性、安全发布等内容
在Java并发编程中,数据的封装与访问控制、线程安全性的考量、同步机制的使用是重要的基础概念和技巧。以下是从给出的文件内容中提取出的详细知识点: 1. 数据封装与访问控制:确保内部私有数据不被轻易访问,并且...
《Java并发编程实战》个人读书笔记,非常详细: 1 简介 2 线程安全性 3 对象的共享 4 对象的组合 5 基础构建模块 6 任务执行 7 取消与关闭 8 线程池的使用 9 图形用户界面应用程序 10 避免活跃性危险 11 性能与可...
Java并发编程实践笔记 Java并发编程实践笔记是一份关于Java并发编程的实践笔记,涵盖了多种关于线程安全、并发编程的实践经验和原则。下面是从笔记中总结的知识点: 1. 保证线程安全的三种方法:不要跨线程访问...
### Java并发编程笔记 #### 实现Runnable接口与继承Thread类 在Java中,实现多线程功能主要有两种途径:一种是通过实现`Runnable`接口,另一种则是通过继承`Thread`类。这两种方式各有优劣,具体选择哪一种取决于...
### Java并发编程学习笔记知识点详解 #### 一、Java并发编程概述 Java并发编程是指在Java应用程序中同时执行多个操作的技术。它通过多线程、线程池等机制实现资源的有效利用,提高程序运行效率。Java并发编程的...
本文将基于文档《Java并发编程与高并发解决方案-学习笔记***.pdf》中提供的内容,来详细阐述并发编程和高并发的基本概念、CPU多级缓存与缓存一致性、以及Java内存模型。 ### 并发与高并发概念 在现代多线程编程中...
读书笔记:Java并发编程之美读书笔记
《java并发编程实战》读书笔记-第2章-线程安全性,脑图形式,使用xmind8制作 包括引言、线程安全性定义、原子性、加锁机制、使用锁保护状态、活跃性与性能等内容
《java并发编程实战》读书笔记-第3章-对象的共享,脑图形式,使用xmind8制作 包括线程安全类设计、实例封闭、线程安全性委托、现有线程安全类中添加功能和文档化同步策略等内容