循环打印积偶数 java_java交替打印奇偶数问题,会出现2个线程都wait阻塞了

我来回答一波。

你可以先将 Thread2 的代码做以下两种修改,一种是:

public static class MyThread2 extends Thread {

@Override

public void run() {

while( true ) {

synchronized( OBJ ) {

out.println(Thread.currentThread().getName() + " enter---- " + i);

if( i % 2 == 1 ) {

out.println(Thread.currentThread().getName() + " " + i++);

out.println(Thread.currentThread().getName() + " notify");

OBJ.notify();

} else {

try {

out.println(Thread.currentThread().getName() + " wait");

OBJ.wait();

out.println(Thread.currentThread().getName() + " wait over");

} catch( InterruptedException e ) {

e.printStackTrace();

}

}

out.println(Thread.currentThread().getName() + "leave--- " + i);

}

try {

Thread.sleep(1000);

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

}

另外一种是:

public static class MyThread2 extends Thread {

@Override

public void run() {

while( true ) {

synchronized( OBJ ) {

out.println(Thread.currentThread().getName() + " enter---- " + i);

if( i % 2 == 1 ) {

out.println(Thread.currentThread().getName() + " " + i++);

out.println(Thread.currentThread().getName() + " notify");

OBJ.notify();

} else {

try {

out.println(Thread.currentThread().getName() + " wait");

OBJ.wait();

out.println(Thread.currentThread().getName() + " wait over");

} catch( InterruptedException e ) {

e.printStackTrace();

}

}

out.println(Thread.currentThread().getName() + "leave--- " + i);

}

Thread.yield();

}

}

}

这两种改法你分别运行一下,会发现第一种改法运行以后能得到你想要的结果。

而第二种改法,答案是不一定,并且最终极大可能还是会把两个线程堵死。

你的代码的运行结果跟你的预期不符,主要你忽视了两点:

CPU时间片

wait被notify后,不会立即获得锁。

Java 的对象锁的实现采用的是Monitor机制,具体机制如下,你也可以参考我写过的一篇文章:

9a5ff43f67ce787fca20e41e900ce9c3.png

当一个线程需要获取 Object 的锁时,会被放入 EntrySet 中进行等待,如果该线程获取到了锁,成为当前锁的 owner。如果根据程序逻辑,一个已经获得了锁的线程缺少某些外部条件,而无法继续进行下去(例如生产者发现队列已满或者消费者发现队列为空),那么该线程可以通过调用 wait 方法将锁释放,进入 wait set 中阻塞进行等待,其它线程在这个时候有机会获得锁,去干其它的事情,从而使得之前不成立的外部条件成立,这样先前被阻塞的线程就可以重新进入 EntrySet 去竞争锁。

你的Thread2调完notify后,Thread1等到Thread2释放锁以后,它还得和 Thread2 站在同一条起跑线上去竞争锁,所以没有绝对地说Thread2释放锁以后,Thread1一定就轮到它获得锁。

你的代码每次都运行相同的结果,原因主要在于 Thread2 会比 Thread1 更容易重新获得锁,因为Thread2的CPU时间片极大可能还没用完。

我们上面的修改,第一种修改是让 Thread2 sleep 一秒,这绝对能让Thread1 有充足的时间获取锁,所以运行结果会如你所预期。

第二种修改是让 Thread2 让出 CPU 时间片,但是同样,CPU 在重新选择线程运行的时候,至少会有一半的机会还是会选中 Thread2。

以上。希望能帮到你。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值