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();
}
}
}
}
}
...全文
241 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了,所以唤醒条件永远达不到,于是造成死循环
英文版:Java Concurrency in Practice 内容简介 《JAVA并发编程实践》随着多核处理器的普及,使用并发成为构建高性能应用程序的关键。Java 5以及6在开发并发程序中取得了显著的进步,提高了Java虚拟机的性能以及并发类的可伸缩性,并加入了丰富的新并发构建块。在《JAVA并发编程实践》中,这些便利工具的创造者不仅解释了它们究竟如何工作、如何使用,还阐释了创造它们的原因,及其背后的设计模式。 编辑推荐 《JAVA并发编程实践》既能够成为读者的理论支持,又可以作为构建可靠的、可伸缩的、可维护的并发程序的技术支持。《JAVA并发编程实践》并不仅仅提供并发API的清单及其机制,还提供了设计原则、模式和思想模型,使我们能够更好地构建正确的、性能良好的并发程序。《JAVA并发编程实践》适合于具有一定Java编程经验的程序员、希望了解Java SE 5以及6在线程技术上的改进和新特性的程序员,以及Java并发编程的爱好者。 作者简介 作者:(美)戈茨 等 本书作者系lava标准化组织(Java Cotl]munity Process)JSR 166专家组(并发工具)的主要成员,同时他们还致力于其他多个JCP专家组织。Brain Goetz是一位拥有二十年行业经验的软件咨询师,发表过超过75篇关于。Java开发的文章。Tim Peierls是现代多处理器的权威,在BoxPop.biz、唱片艺术和戏剧表演上也造诣颇深。Joseph Bowbeer是一位Java ME专家,他对并发编程的痴迷始于在Apollo计算机上编程的岁月。David Holmes是《The Java TM Programmjng LangLJage》的合著者,目前就职于Sun Microsysterns。Joshua Bloch是Google的首席Java架构师,《Effective Java》的作者、《3ava PLizzlers》的合著者,他不像他的兄弟(his brother,Bloctl与Neal主持的Java编程专栏里虚构的人物)那样编程,从来都不。Doug Lea是《Corlcurrent Progra r11ming in Java》的作者,SUNY Oswego大学计算机科学的教授。

51,411

社区成员

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

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