maomaoysq 2009-10-30 14:44
浏览 547
已采纳

java的多线程问题,结果出现负数情况

预想实现轮番取[color=red]单数[/color]票和[color=red]双号[/color]票的多线程出票过程

执行结果发现:
如果只执行两个进程,程序会卖出票号为“0”的票,如果再增加出票的线程就出现线程为[color=red]负[/color]数的情况了

[code="java"]
public class myFirst
{
public static void main(String[] args)
{
Q q = new Q();
new Thread(new SaleS(q)).start();
new Thread(new SaleD(q)).start();
new Thread(new SaleS(q)).start();
new Thread(new SaleD(q)).start();
}
}
class Q
{
private int tickets = 10;
public synchronized int get()
{
return tickets;
}
public synchronized void saleSingle()
{
if(tickets>0)
{
if(tickets % 2 ==0)
{
try {
wait();
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
try
{
Thread.sleep(1000);
}
catch(InterruptedException e){}
System.out.println(Thread.currentThread().getName()+
" is salling ticket "+ tickets--);
notify();
}
}
public synchronized void saleDouble()
{
if(tickets>0)
{
if(tickets % 2 ==1)
{
try {
wait();
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
try
{
Thread.sleep(1000);
}
catch(InterruptedException e){}
System.out.println(Thread.currentThread().getName()+
" is salling ticket "+ tickets--);
notify();
}
}
}
class SaleS implements Runnable
{
Q q = null;
public SaleS(Q q)
{this.q = q;}
public void run()
{
while(q.get()>=1)
{
q.saleSingle();
}
}
}
class SaleD implements Runnable
{
Q q = null;
public SaleD(Q q)
{this.q = q;}
public void run()
{
while(q.get()>=2)
{
q.saleDouble();
}
}
}
[/code]

  • 写回答

1条回答 默认 最新

  • JavaHero080 2009-11-02 15:33
    关注

    你的方法都[code="java"]synchronized[/code]了,也就意味着,当某一个线程在执行[code="java"]saleSingle()[/code]或者[code="java"]saleDouble()[/code]时,虽然检查了奇偶性,但在[code="java"]wait()[/code]时,其它线程是无法执行这些同步化方法时(single或double,都一起被上锁了)。
    所以结果是wait()结束然后出票,此时你并未做检查,所以不一定正确。
    逻辑上你必须不断wait只到条件成熟,比如把if改成while。不过那样很有可能死锁。你必须重新设计一下代码结构,最好不要[code="java"]synchronized[/code]整个方法,只要[code="java"]synchronized[/code]其实一段就可以了。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 #MATLAB仿真#车辆换道路径规划
  • ¥15 java 操作 elasticsearch 8.1 实现 索引的重建
  • ¥15 数据可视化Python
  • ¥15 要给毕业设计添加扫码登录的功能!!有偿
  • ¥15 kafka 分区副本增加会导致消息丢失或者不可用吗?
  • ¥15 微信公众号自制会员卡没有收款渠道啊
  • ¥100 Jenkins自动化部署—悬赏100元
  • ¥15 关于#python#的问题:求帮写python代码
  • ¥20 MATLAB画图图形出现上下震荡的线条
  • ¥15 关于#windows#的问题:怎么用WIN 11系统的电脑 克隆WIN NT3.51-4.0系统的硬盘