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实现的