帮忙理一下多线程的一个例子程序。

koyota86 2010-03-23 11:27:37
class MyThread implements Runnable
{
private int ticket = 5 ; // 假设一共有5张票
public void run(){
for(int i=0;i<100;i++)
{
this.sale();
}
}
public void sale()
{
if(this.ticket>0)
{ // 还有票
try
{
Thread.sleep(2000) ; // 加入2秒延迟
}catch(InterruptedException e){
e.printStackTrace() ;
}
System.out.println(Thread.currentThread().getName()+" 卖票:ticket = " + ticket-- );
}
}
};
public class SyncDemo01{
public static void main(String args[]){
MyThread mt = new MyThread() ; // 定义线程对象
Thread t1 = new Thread(mt) ; // 定义Thread对象
Thread t2 = new Thread(mt) ; // 定义Thread对象
Thread t3 = new Thread(mt) ; // 定义Thread对象
t1.start() ;
t2.start() ;
t3.start() ;
}
};

运行结果:
Thread-1 卖票:ticket = 5
Thread-0 卖票:ticket = 3
Thread-2 卖票:ticket = 4
Thread-1 卖票:ticket = 2
Thread-2 卖票:ticket = 1
Thread-0 卖票:ticket = 2

问题:这个结果怎么出来的呢,怎么看着很不可能啊?
为什么每一个线程对象的ticket起始值不是5?
...全文
110 9 打赏 收藏 转发到动态 举报
写回复
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
fengboxjtu556 2010-04-13
  • 打赏
  • 举报
回复
线程的确是一个很闹心的问题
koyota86 2010-04-12
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 qybao 的回复:]
如何不可能了?
三个线程引用同一个mt对象,起始值是mt.ticket的当前值,也就不都是5了
没有同步,线程的执行是随机分配的,
程序执行结果分析:
第一,Thread-1 卖票:ticket = 5 当Thread-1先执行时,进入sale,睡眠2秒,然后打印ticket 5,ticket变为4
第二,接着Thread-2执行,睡眠2秒,然后执行字符串相加Thread.current……
[/Quote]

谢谢!!!!!!!!!!!!! 您好认真啊。
qybao 2010-03-24
  • 打赏
  • 举报
回复
如何不可能了?
三个线程引用同一个mt对象,起始值是mt.ticket的当前值,也就不都是5了
没有同步,线程的执行是随机分配的,
程序执行结果分析:
第一,Thread-1 卖票:ticket = 5 当Thread-1先执行时,进入sale,睡眠2秒,然后打印ticket 5,ticket变为4
第二,接着Thread-2执行,睡眠2秒,然后执行字符串相加Thread.currentThread().getName()+" 卖票:ticket = " + ticket-- ,此时字符串中的ticke是4,而ticke变量是3,但是还没来得及print,Thead-2的分配时间完了,换Thread-0
第三,接着Thread-0执行,跟Threa-1一样,先睡2秒,然后打印,有第二可知,此时ticke是3,所以打印3,然后ticket变为2,此时又轮到Thread-2活起来了
第四,Thread-2继续未完成的print,有第二可知,字符串的ticket是4,所以打印4
第五,此时又轮到Thread-1活了,跟第二一样,进行了字符串相加,字符串中的ticket是2,但是ticket--还没来得执行,ticket还是2,Thread-1的分配时间又结束了,轮到Thread-0执行
第六,Thread-0执行,进行字符串相加,由第五可知,此时ticket还是2,所以字符串的ticket是2,然后ticket--,ticket变为1,还未来得及print,Thread-0的分配时间又结束了,轮到Thread-2
第七,Thread-2执行,进行字符串相加,字符串中的ticket是1,[然后ticket--,ticket变为0](这里是否执行了不可知),还未来得及打印Thread-2的分配时间又完了,此时又轮到Thread-1活了
第八,Thread-1接着未完成的ticket--,然后ticket变为0或-1(如果第七执行了ticket--的话),由第五可知,字符串的ticket是2,所以打印ticket 2,此时又轮到Thread-2活了
第九,Thread-2继续未完成的print,打印ticket 1,此时又轮到Thread-0活了
第十,Thread-0继续问完成的print,打印ticket 2
由第七或第八可知,之后的ticket就是0或者小于0,所以sale的if不会再进去,所以也就没有打印了,直到
run的for循环结束,程序退出

不知道LZ能不能看明白
ramparter 2010-03-24
  • 打赏
  • 举报
回复
因为int ticket在run(){}之外,,3个线程都可以对int ticket进行访问和修改。。

程序里的 ticket 没有进行保护 用synchornized 或者 lock 对run()方法上锁
一头头 2010-03-24
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 qybao 的回复:]
如何不可能了?
三个线程引用同一个mt对象,起始值是mt.ticket的当前值,也就不都是5了
没有同步,线程的执行是随机分配的,
程序执行结果分析:
第一,Thread-1 卖票:ticket = 5 当Thread-1先执行时,进入sale,睡眠2秒,然后打印ticket 5,ticket变为4
第二,接着Thread-2执行,睡眠2秒,然后执行字符串相加Thread.currentThread().getName()+" 卖票:ticket = " + ticket-- ,此时字符串中的ticke是4,而ticke变量是3,但是还没来得及print,Thead-2的分配时间完了,换Thread-0
第三,接着Thread-0执行,跟Threa-1一样,先睡2秒,然后打印,有第二可知,此时ticke是3,所以打印3,然后ticket变为2,此时又轮到Thread-2活起来了
第四,Thread-2继续未完成的print,有第二可知,字符串的ticket是4,所以打印4
第五,此时又轮到Thread-1活了,跟第二一样,进行了字符串相加,字符串中的ticket是2,但是ticket--还没来得执行,ticket还是2,Thread-1的分配时间又结束了,轮到Thread-0执行
第六,Thread-0执行,进行字符串相加,由第五可知,此时ticket还是2,所以字符串的ticket是2,然后ticket--,ticket变为1,还未来得及print,Thread-0的分配时间又结束了,轮到Thread-2
第七,Thread-2执行,进行字符串相加,字符串中的ticket是1,[然后ticket--,ticket变为0](这里是否执行了不可知),还未来得及打印Thread-2的分配时间又完了,此时又轮到Thread-1活了
第八,Thread-1接着未完成的ticket--,然后ticket变为0或-1(如果第七执行了ticket--的话),由第五可知,字符串的ticket是2,所以打印ticket 2,此时又轮到Thread-2活了
第九,Thread-2继续未完成的print,打印ticket 1,此时又轮到Thread-0活了
第十,Thread-0继续问完成的print,打印ticket 2
由第七或第八可知,之后的ticket就是0或者小于0,所以sale的if不会再进去,所以也就没有打印了,直到
run的for循环结束,程序退出

不知道LZ能不能看明白[/Quote]

真不是一般人啊 哥哥
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 qybao 的回复:]

如何不可能了?
三个线程引用同一个mt对象,起始值是mt.ticket的当前值,也就不都是5了
没有同步,线程的执行是随机分配的,
程序执行结果分析:
第一,Thread-1 卖票:ticket = 5 当Thread-1先执行时,进入sale,睡眠2秒,然后打印ticket 5,ticket变为4
第二,接着Thread-2执行,睡眠2秒,然后执行字符串相加Thread.curren……
[/Quote
不会吧,这么多?
xiesisi3 2010-03-24
  • 打赏
  • 举报
回复
三个线程引用同一个mt对象

知道这个就够了
Ark032425 2010-03-24
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 qybao 的回复:]
如何不可能了?
三个线程引用同一个mt对象,起始值是mt.ticket的当前值,也就不都是5了
没有同步,线程的执行是随机分配的,
程序执行结果分析:
第一,Thread-1 卖票:ticket = 5 当Thread-1先执行时,进入sale,睡眠2秒,然后打印ticket 5,ticket变为4
第二,接着Thread-2执行,睡眠2秒,然后执行字符串相加Thread.current……
[/Quote]
详细
二重天 2010-03-24
  • 打赏
  • 举报
回复
问下楼主,thinking in java 这本书的下载地址是?
相关推荐

62,568

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告