黑马程序员技术交流社区
标题:
关于多线程的问题
[打印本页]
作者:
杜成龙
时间:
2013-6-12 20:14
标题:
关于多线程的问题
本帖最后由 杜成龙 于 2013-6-13 16:56 编辑
class Ticket implements Runnable
{
int tick=100;
boolean flag=true;
Object obj=new Object();
public void run()
{
if(flag)
{
while(true)
{
synchronized(obj)
{
if(tick>0)
{
try{Thread.sleep(10);}catch(Exception e){}
System.out.println(Thread.currentThread().getName()+" code"+tick--);
}
}
}
}
else
while(true)
show();
}
public synchronized void show()
{
if(tick>0)
{
try{Thread.sleep(10);}catch(Exception e){}
System.out.println(Thread.currentThread().getName()+" show"+tick--);
}
}
}
class TicketDemo4
{
public static void main(String[] args)
{
Ticket t=new Ticket();
Thread t1=new Thread(t);
Thread t2=new Thread(t);
t1.start();
try{Thread.sleep(10);}catch(Exception e){}
t.flag=false;
t2.start();
}
}
复制代码
程序的运行结果有些疑惑,想请教一下,
当程序中执行t.flag=false后,就把flag改成了false状态了,按说线程就不会执行同步代码块中的内容了,会去执行同步函数中的内容,
但是为什么运行的结果中在出现Thread-1后又会出现Thread-0呢?还有就是t2开启后,t1也还是开启的,按说t1也能进入同步函数中去执行,为什么
同步函数中只有t2线程,也就是Thread-1线程呢?(注:t1线程对应的是Thread-0线程,t2线程对应的是Thread-1线程)
作者:
ying_1990
时间:
2013-6-12 23:19
class TicketDemo4
{
public static void main(String[] args)
{
Ticket t=new Ticket();
Thread t1=new Thread(t);
Thread t2=new Thread(t);
t1.start();
//try{Thread.sleep(10);}catch(Exception e){} //试试将该句注释掉,是不是你想要的结果?
t.flag=false;
t2.start();
}
}
作者:
小冰块
时间:
2013-6-12 23:21
本帖最后由 小冰块 于 2013-6-12 23:37 编辑
亲,其实你这两个问题都是一个问题,那就是为什么T1始终在同步代码块中,而T2始终在同步函数中。
你看,刚开始的时候flag是true,T1先跑,趁着主线程睡觉的时候进入到了同步代码块code中,然后T2等醒来的时候发现flag已经变成了false,所以只能去同步函数show中,然后他们一直保持在这样的一个状态里。
为什么会一直保持这样的状态呢?因为你的T1自从判断过一个flag=true并进入代码块中后,就再也没出过代码块中的while循环(因为while始终为true),所以就再也没有判断该flag。
同样的,你的show函数的前提也是while(true),所以T2就一直在同步函数中,两个线程就各自在各自的地盘互不干扰的玩了。
另外帮你改了一下程序,这样T1和T2可以随机的进出同步代码块和同步函数,而不破坏同步性:
class Ticket implements Runnable
{
int tick=100;
boolean flag=true;
Object obj=new Object();
public void run()
{
while(true) //把while定义到if和else的外面,而不是只循环if
{
if(flag) //内层循环去掉,每次输出一次后都会重回while的顶端重新判断if(flag)
{
synchronized(obj)
{
if(tick>0)
{
try{Thread.sleep(10);}catch(Exception e){}
System.out.println(Thread.currentThread().getName()+" code"+tick--);
flag = false; //如果进来的时候状态是true,卖掉一张票后改变标记
}
}
}
else
show();
}
}
public synchronized void show()
{
if(tick>0)
{
try{Thread.sleep(10);}catch(Exception e){}
System.out.println(Thread.currentThread().getName()+" show"+tick--);
flag = true; //同样要记得改变标记,不然标记就固定死了
}
}
}
class TicketDemo4
{
public static void main(String[] args)
{
Ticket t=new Ticket();
Thread t1=new Thread(t);
Thread t2=new Thread(t);
t1.start();
try{Thread.sleep(10);}catch(Exception e){}
t.flag=false;
t2.start();
}
}
复制代码
作者:
ying_1990
时间:
2013-6-12 23:41
学习了,论坛果然暗藏高手,多逛论坛可以学到更多知识{:soso_e128:}
作者:
孙百鑫
时间:
2013-6-13 06:37
楼主您好!如果问题得到解决请将题目改成"已解决"
编辑文章-->修改 如果问题没有得到解决请继续发问谢谢您的配合{:soso_e100:}
作者:
杜成龙
时间:
2013-6-13 17:21
小冰块 发表于 2013-6-12 23:21
亲,其实你这两个问题都是一个问题,那就是为什么T1始终在同步代码块中,而T2始终在同步函数中。
你看,刚 ...
受教了,谢谢啦~{:soso_e100:}
欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/)
黑马程序员IT技术论坛 X3.2