java并发问题

liangwenli2 2018-10-22 06:59:54
想自己编了一个MyCyclicBarrier类,主要在await()方法内部对实例的count执行-1操作,在每个MyCyclicBarrier实例化的时候,新建一个守护线程(CheckAndRelease的实例),该实例run方法内部执行循环检查,当发现count值被减到0,则将count值复位,并执行一个善后runnable(这种一般是执行搜集数据等操作,为了简单起见,我只是用它打印一行字),最后通过notifyAll()唤醒所有等待MyCyclicBarrier 实例锁的线程。
问题是,在MyCyclicBarrier的await()方法中,如果用while循环检查count的值,程序运行结果达不到目标,将while改为if,则结果正确,请问什么原因?


import java.util.concurrent.TimeUnit;
public class MyCycliBarrier {

public volatile int count;
public Runnable endWait;
public volatile int realCount;
public MyCycliBarrier(int size,Runnable runnable)
{
this.count = size;
this.realCount = size;
this.endWait = runnable;
CheckAndRelease<MyCycliBarrier> checkAndRelease = new CheckAndRelease<MyCycliBarrier>(this);
new Thread(checkAndRelease).start();
}
public synchronized void await() {

try {
count--;
while(count!=realCount) {
wait();
}
} catch (InterruptedException e) {
Print.p("myCyclicBarrier interrupted");
}
}
public static void main(String[] args)
{

MyCycliBarrier cycliBarrier = new MyCycliBarrier(5, new Runnable() {
@Override
public void run() {
System.out.println("CycliBarrier Over");
}
});
for(int i=0;i<5;i++)
{
new Thread(new MyStringProducer(cycliBarrier)).start();
}

}
}
class MyStringProducer implements Runnable{

MyCycliBarrier myCycliBarrier;
public MyStringProducer( MyCycliBarrier m)
{
this.myCycliBarrier = m;
}
@Override
public void run() {
for(int i=0;i<5;i++)
{
System.out.println(Thread.currentThread()+" "+i);
myCycliBarrier.await();
}
}
}
class CheckAndRelease<T extends MyCycliBarrier> implements Runnable
{
T t;
public CheckAndRelease(T a)
{
this.t = a;
}

@Override
public void run() {
while(!Thread.interrupted())
{

if(t.count==0)
{
synchronized (t)
{
t.count = t.realCount;
new Thread(t.endWait).start();
try {
TimeUnit.NANOSECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
t.notifyAll();
}
}
}
}
}
...全文
250 2 打赏 收藏 转发到动态 举报
写回复
用AI写文章
2 条回复
切换为时间正序
请发表友善的回复…
发表回复
liangwenli2 2018-11-25
  • 打赏
  • 举报
回复
引用 1 楼 qybao 的回复:
程序逻辑有问题,用while死循环了吧 你创建5个MyStringProducer线程,每个线程执行5遍await 你的CheckAndRelease线程在check t.count==0 并没有加锁 第一次5个MyStringProducer线程执行的时侯可能正常,但第二次是notifyall后,线程执行顺序是随机的,有些线程被唤醒执行while判断不符合,退出循环了,但那同时又有可能CPU优先继续直线下一次await,先执行count--,此时有些线程刚被唤醒执行while,而while一直符合条件所以继续wait,这样count--因为一直while成立而wait的线程就达不到0了,所以唤醒条件永远达不到,于是造成死循环
十分感谢,后面我自己试验也得到了同样的结论,
qybao 2018-10-25
  • 打赏
  • 举报
回复
程序逻辑有问题,用while死循环了吧 你创建5个MyStringProducer线程,每个线程执行5遍await 你的CheckAndRelease线程在check t.count==0 并没有加锁 第一次5个MyStringProducer线程执行的时侯可能正常,但第二次是notifyall后,线程执行顺序是随机的,有些线程被唤醒执行while判断不符合,退出循环了,但那同时又有可能CPU优先继续直线下一次await,先执行count--,此时有些线程刚被唤醒执行while,而while一直符合条件所以继续wait,这样count--因为一直while成立而wait的线程就达不到0了,所以唤醒条件永远达不到,于是造成死循环

51,412

社区成员

发帖
与我相关
我的任务
社区描述
Java相关技术讨论
javaspring bootspring cloud 技术论坛(原bbs)
社区管理员
  • Java相关社区
  • 小虚竹
  • 谙忆
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧