当前位置:编程学习 > JAVA >>

新人求教多线程疑惑

新手一枚,最近看孙鑫老师的Java视频,讲到多线程的时候,有这么一段代码。
class TicketsSystem
{
public static void main(String[] args)
{
SellThread st=new SellThread();

new Thread(st).start();
new Thread(st).start();
new Thread(st).start();
new Thread(st).start();
}
}

class SellThread implements Runnable
{
int tickets=100;
Object obj=new Object();
public void run()
{
while(true)
{
synchronized(obj)
{
try
{
Thread.sleep(10);
}
catch(Exception e)
{
e.printStackTrace();
}
if(tickets>0)
{

System.out.println("obj:"+Thread.currentThread().getName()+
" sell tickets:"+tickets);
tickets--;
}
}
}
}
}


这四个线程分别叫T0,T1,T2,T3。在我理解看来:
1.T0锁定obj后,进入sleep 10ms,将运行权交给T1
2.T1发现obj被锁后,将运行权交给T2
3.同理T2交给T3,T3交还T0
4.此时T0往下运行,输出ticket号,然后解锁obj,由于是while(true),继续循环加锁obj
然后还是按1→2→3→4这么循环下来,那T1,T2,T3应该是没有执行到的机会

除非是T0刚好在解锁obj后、未进入下一次循环加锁obj之前,时间片到期,那其他线程才有执行的可能。但是会这么巧,刚好时间片在执行解锁完后到期吗?

从实际输出结果看,各个线程都是有执行过一段时间的。不知道哪个地方理解有误,求解。。。 多线程 时间片 线程同步 --------------------编程问答-------------------- 别人一直在那等呢,你一放,别人马上就去竞争了,而你还要做些动作重新加入竞争者中;时间片切换也会导致切换 --------------------编程问答--------------------
引用 1 楼 ticmy 的回复:
别人一直在那等呢,你一放,别人马上就去竞争了,而你还要做些动作重新加入竞争者中;时间片切换也会导致切换

别人竞争的时候发现obj被锁了,他也没办法继续向下运行啊。。。 --------------------编程问答-------------------- Thread.sleep 并不会释放所持有的对象锁,而是堵在那里了。
锁对象的 wait 方法可以让当前线程阻塞的同时,将对象锁释放掉。 --------------------编程问答-------------------- 这四个线程分别叫T0,T1,T2,T3。在我理解看来:
1.T0锁定obj后,进入sleep 10ms,将运行权交给T1
2.T1发现obj被锁后,将运行权交给T2
3.同理T2交给T3,T3交还T0
4.此时T0往下运行,输出ticket号,然后解锁obj,由于是while(true),继续循环加锁obj

这里给楼主提个问题:
T0运行完为什么一定是将运行权交给T1?

除非是T0刚好在解锁obj后、未进入下一次循环加锁obj之前,时间片到期,那其他线程才有执行的可能。但是会这么巧,刚好时间片在执行解锁完后到期吗?

这里也给楼主提个问题:
在不止一个CPU的情况下,为什么第二个线程一定要等着第一个线程运行完才有CPU资源?

楼主去找一个单核的CPU,双核的,4核的都试一下上面的程序,看看结果。 --------------------编程问答--------------------
引用 3 楼 bao110908 的回复:
Thread.sleep 并不会释放所持有的对象锁,而是堵在那里了。
锁对象的 wait 方法可以让当前线程阻塞的同时,将对象锁释放掉。

嗯啊,我知道不会解锁,只是堵了后交出运行权(单核cpu),那此时别的线程由于未解锁所以无法执行,我记得孙鑫老师执行的结果是每个线程轮流执行一次输出,他应该是单核电脑,04年的视频了,不清楚为什么别的线程也执行了。除非时间片刚好在解锁obj后、未进入下一次循环加锁obj之前这个点切换了。是吗? --------------------编程问答--------------------
引用 4 楼 kittaaron 的回复:
这四个线程分别叫T0,T1,T2,T3。在我理解看来:
1.T0锁定obj后,进入sleep 10ms,将运行权交给T1
2.T1发现obj被锁后,将运行权交给T2
3.同理T2交给T3,T3交还T0
4.此时T0往下运行,输出ticket号,然后解锁obj,由于是while(true),继续循环加锁obj

这里给楼主提个问题:
T0运行完为什么一定是将运行权交给T1?

除非是T0刚好在解锁obj后、未进入下一次循环加锁obj之前,时间片到期,那其他线程才有执行的可能。但是会这么巧,刚好时间片在执行解锁完后到期吗?

这里也给楼主提个问题:
在不止一个CPU的情况下,为什么第二个线程一定要等着第一个线程运行完才有CPU资源?

楼主去找一个单核的CPU,双核的,4核的都试一下上面的程序,看看结果。


1.T0到T3的顺序和它start的顺序没关系么?不清楚系统是按什么顺序来调度的,但是和我的问题没多大关系,反正意思是它把运行权交出去了。。。
2.这里就讨论单核情况哦,多核的我再去看看。孙鑫老师的结果是每个线程按次序执行输出一次,循环到100扣完为止。 --------------------编程问答-------------------- 一句话,Thread.sleep(10);不会释放对象锁. --------------------编程问答--------------------
引用 7 楼 toss2000 的回复:
一句话,Thread.sleep(10);不会释放对象锁.

嗯啊,释放对象锁是在synchronized(obj){...}大括号执行完之后,我没理解错吧。 --------------------编程问答-------------------- 其实在同一时间点上,cpu只有一个线程在运行,但是由于它的运算速度太快,所以给我们的感觉是所有线程都在进行。双核或者以上的cpu才能做到真正意义上的多线程。


所以4楼朋友问得很好。
补充:Java ,  Java SE
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,