性能问答>线程的join方法结合Lambda表达式出现的一个问题>
11回复

线程的join方法结合Lambda表达式出现的一个问题



具体问题如图所示。

image.png

4637 阅读
请先登录,再评论

image.png image.png main线程初始化Test类过程中调用到了线程t,而线程t 执行过程中又依赖了Test类的方法(lambda解语法糖之后的方法调用,调用方法前需要完成这个类的类加载过程),死锁了。匿名内部类写法也是会创建另一个类,这种情况和lambda有一样的问题。

2年前

没有atomicLong变量,线程中的打印语句也执行不了啊

2年前
回复 残月@诗雨_393862:

不加这个变量,也是一样的原因是new Thread(()->{}),会在Test类里新增一个lambda静态方法,而生成的Runnable的proxy class会调用Test的这个静态方法,这种情况下测试线程也会触发Test类的初始化动作,从而发生了互锁

2年前回复

java 文件 image.png
编译后文件 image.png
当用双冒号引用时就不发生阻塞抢锁现象,
我理解是 是因为局部变量var10002 指到了i, 然后操作var10002 时不用 获取锁检测初始话判断,所以就不堵塞了是吗?
t线程中用的是var10002 可不可理解为 局部变量不检测初始化动作

12年前
回复 你假笨:

👏👏👏 豁然开朗

2年前回复
回复 Yc_453752:

这个过程可能比较复杂,主要涉及到invokeDynamic,简单的回答是new Thread(i::getAndIncrement);会动态创建一个proxy class,这个proxy class会实现Runnable接口,同时讲i作为参数传给对应的构造函数,因此当测试当另外一个线程执行的时候,其实根本就不会和main class相关,因此那把锁对另外的线程没有任何影响,也就是新创建的线程执行的时候不会有任何主类的依赖,从而不需要做主类的初始化动作

2年前回复

我可以贴一下这块的代码
image.png
这里的锁对象其实一个int[],长度为0,
image.png

所以大家可以可以到PerfMa的内存分析产品XElephant上可以验证下
https://memory.console.heapdump.cn/detail/29833/object/inbound?hexAddress=0x6c8132698&%24newtab=1&%24tabname=int%5B0%5D&%24type=object
这个int[0]其实就是某个类初始化的时候的锁对象,只不过因为已经初始化好了,所以可以被回收了
image.png

2年前

和是否匿名类关系不大吧?主要原因是类初始化的过程会持有一把锁,当执行t.start()之前,main线程会持有Test类对应的一把初始化锁,然后当测试线程运行的时候会获取i的静态变量,此时又会去做类初始化的一些判断,此时也会去拿那把锁,而导致两个线程互锁了,因为main线程有调用了t.join,会导致这把锁main线程一直不释放,从而导致两个线程都锁死

12年前
回复 你假笨:

如果去掉上面的那个i变量,匿名类和lambda还是有区别的,lambda会互锁,但是匿名类写法没问题,主要原因是lambda会在Test类里创建一个private static的method,将lambda里的逻辑放到这个method里执行,然后再创建一个Test的内部类实现Runnable接口,在run方法里会调用Test里新建的private static的method,而调用这个方法也需要Test类的初始化,从而发生互锁

2年前回复
回复 你假笨:

明白了

2年前回复
回复 你假笨:

好的,谢谢!😍😍

2年前回复