`
BruceChan_GY
  • 浏览: 6974 次
社区版块
存档分类
最新评论

《Java并发编程的艺术》读书笔记三

    博客分类:
  • JVM
阅读更多
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实现的
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics