范之孤
建立
qq_LZ毛荣荣_0
窗口1卖了一张票,打印剩余票数为2(输出结果第三行). 然后CPU资源被窗口2占用,执行了卖票操作,但是还没有执行打印输出操作。然后窗口1获取CPU资源执行操作继续卖票,打印(输出第四行)。窗口1操作完毕,然后窗口2获取CPU资源执行最后的输出打印操作(第五行)。
忽职守
奥 明白了
慕函数0603164
是因为线程的执行顺序啊,每次执行都不一定是一样的。至于剩余票的问题,老师有回答啊~o(^_^)o
丶子非鱼
public void run() {
// TODO Auto-generated method stub
while(true){
synchronized(lockObj){
if(ticketsNum>0){
ticketsNum--;
System.out.println(Thread.currentThread().getName()+"卖出一张票,剩余"+ticketsNum);
//Thread.yield();
lockObj.notifyAll();
}
}
}
}这样改就能按顺序输出了
皓腕凝雪
因为创建线程时 第二个参数 默认是线程名称
_菲菲菲菲
因为其实字符串在之前就已经拼接好了,只是当一号线程重新拿到cpu资源时才打印出来
246小言
窗口3卖了一张票,剩余票数:2 为什么还能声誉三张票 不是runable接口嘛
_三_毳
这种情况的解决办法应该可以用线程同步解决
紫叶_1
使用synchronized 对减少票的方法进行同步修饰
微微shirly
可能是因为并非窗口1首先获得CPU时间片,而是其他线程。
首先是窗口2 ,执行到count--之后,sysout时就被阻塞了。注意此时count=4。
然后是窗口1 ,执行了整个run方法 ,此时count=3。
然后是窗口3 ,执行了整个run方法 ,此时count=2。
此时窗口2恢复,继count--之后执行,输出count=3。
然后是窗口3 ,执行了整个run方法 ,此时count=0。
当然这种并不一定是这样,因为现在的多核CPU线程是可以同时执行的。
在路口出口
补充一个解决办法
路与路之间
extends Thread的例子没有问题。想实现的确实是3个窗口总共有5张票,老师故意用extends Thread的例子,就是为了说明这种方式达不到希望的效果(即实际出现的效果是你所说的“每个窗口拥有5张票”)。老师也在PPT中写明,只有Runnable的方式才适合多个线程处理同一资源的情况。
如果硬要用extends Thread来实现效果,确实像你说的可以加static关键字,但老师想告诉我们的是,对于这样的情况,还是用Runnable好。
沈夜
共用一个变量,已经到0了,while条件就退出了。只会打印一个0.
沈真成是被选召的孩子
你没有加同步块吧?synchroized
朱西瓜
你的理解大致上是对的,但不是刚好打印的时候被窗口2减去一张票,过程是这样的:
当第一个线程获得CPU的时间片后,它的代码恰好执行到println那一行后,刚准备输出(但还没有获得tickets的值),这时候该线程的时间片被剥夺,等待下一次再获得时间片。等到别的线程执行完后,该线程再次获得时间片,它去访问tickets变量,应该tickets变量是被别的线程自减过得,所以获得不是4,而是一个比4小的值。由于这种运算在现在的CPU上很快,就会出现前三个都是2的情况。如果你给println语句加上一个synchronized同步锁,你的结果一会一直是43210.
慕圣5083653
小哥,我回答的怎么样,一定要给我一个最佳答案哦 嘿嘿
路过蜻蜓1209
schronized
慕圣4558451
调用了start方法之后,线程会进入可运行状态(runnable),这时候如果能够抢到cpu时间片,就会执行run方法中的代码.这就意味着执行start方法后,该线程不一定就运行了,是否运行取决于cpu的调度。这是我的理解,希望能对你有所启发。
若水寒冰
要加锁才安全。。。
慕神6851314
小飞飞要忘记烦恼
线程执行的过程不是原子操作,当然可以被其他其他线程交叉进来执行了!不然就不存在线程不安全的问题了!
Flames
要解释的话,可能不是三言两语能够说清楚,而且你也不一定能理解的了,这个问题先放下,留意一下我的下门课程:内存可见性,目前还没上线,下门课程看完就差不多理解了!
fs593
宝慕林3329632
你好,ticketsCont是实例变量,它的值自然是存在堆中(每个java对象在堆中都会占据一定内存,而实例变量的值就是存储在这块内存中,类似于结构体,因此每个对象对应一个ticketsCont的值),ticketsCont跟值传递没有关系啊,如果是Runnable方式的话,传递的也只是MyThread对象引用的副本,不管ticketsCont的事,但是因为ticketsCont的值在引用和引用副本所指向的堆内存中,所以无论是引用还是引用副本改变了堆内存中ticketsCont的值,都会产生效果!