打字猴:1.700451269e+09
1700451269
1700451270 }
1700451271
1700451272 相信读者明白会先输出“m1执行完毕”,然后再输出“m2执行完毕”,因为m1方法在执行时,线程t持有foo对象的锁,要想主线程获得m2方法的执行权限就必须等待m1方法执行完毕,也就是释放当前锁。明白了这个问题,我们思考一下上例中带有synchronized的递归函数是否能执行?会不会产生死锁?运行结果如下:
1700451273
1700451274 *********9
1700451275
1700451276 ********8
1700451277
1700451278 *******7
1700451279
1700451280 ******6
1700451281
1700451282 *****5
1700451283
1700451284 ****4
1700451285
1700451286 ***3
1700451287
1700451288 **2
1700451289
1700451290 *1
1700451291
1700451292 一个倒三角形,没有产生死锁,正常执行,这是为何呢?很奇怪,是吗?那是因为在运行时当前线程(Thread-0)获得了foo对象的锁(synchronized虽然是标注在方法上的,但实际作用的是整个对象),也就是该线程持有了foo对象的锁,所以它可以多次重入fun方法,也就是递归了。可以这样来思考该问题,一个宝箱有N把钥匙,分别由N个海盗持有(也就是我们Java中的线程了),但是同一时间只能由一把钥匙打开宝箱,获取宝物,只有在上一个海盗关闭了宝箱(释放锁)后,其他海盗才能继续打开锁获取宝物,这里还有一个规则:一旦一个海盗打开了宝箱,则该宝箱内的所有宝物对他来说都是开放的,即使是“宝箱中的宝箱”(即内箱)对他也是开放的。可以用以下代码来表述。
1700451293
1700451294 class Foo implements Runnable{
1700451295
1700451296 public void run(){
1700451297
1700451298 method1();
1700451299
1700451300 }
1700451301
1700451302 public synchronized void method1(){
1700451303
1700451304 method2();
1700451305
1700451306 }
1700451307
1700451308 public synchronized void method2(){
1700451309
1700451310 //Do Something
1700451311
1700451312 }
1700451313
1700451314 }
1700451315
1700451316 方法method1是synchronized修饰的,方法method2也是synchronized修饰的,method1调用method2是没有任何问题的,因为是同一个线程持有对象锁,在一个线程内多个synchronized方法重入完全是可行的,此种情况下不会产生死锁。
1700451317
1700451318 那什么情况下会产生死锁呢?看如下代码:
[ 上一页 ]  [ :1.700451269e+09 ]  [ 下一页 ]