黑马程序员技术交流社区
标题:
线程安全问题
[打印本页]
作者:
史卜坤
时间:
2012-7-14 22:29
标题:
线程安全问题
class Ticket implements Runnable
{
private int ticket = 100;
//private String name;
//Ticket(String name)
//{
//this.name = name;
//}
public void run()
{
while(ticket>0)
{
try
{
Thread.sleep(10);
}
catch(Exception e)
{
}
System.out.println(Thread.currentThread().getName()+"sale..."+ticket--);
}
}
}
class ThreadDemo4
{
public static void main(String[] args)
{
Ticket t = new Ticket();
Thread t1 = new Thread(t);
Thread t2 = new Thread(t);
Thread t3 = new Thread(t);
Thread t4 = new Thread(t);
t1.start();
t2.start();
t3.start();
t4.start();
}
}
复制代码
毕老师说这个多线程程序有安全问题,还是不太明白。比如线程0执行时的这个ticket=1>0 进入那个while循环打印,这时ticket=0,若线程2抢到这个执行权它不能进入while循环呀!怎么还能打印呢?
作者:
周刚
时间:
2012-7-14 22:51
本帖最后由 周刚 于 2012-7-14 22:52 编辑
线程2抢到这个执行权它不能进入while循环
?为什么别人线程不能进入while循环?在执行ticket--之前,所有线程执行while(ticket>0)都成立。当然都会打印!
while代码段并不是线程安全的,并没有加任何锁,可以有多个线程同时执行。如下,我票数设置为1:
class Ticket implements Runnable
{
private int ticket = 1;
public void run()
{
while(ticket>0)
{
try
{
Thread.sleep(10);
} catch(Exception e){}
System.out.println(Thread.currentThread().getName()+"sale..."+ticket--);
}
}
}
class ThreadDemo4
{
public static void main(String[] args)
{
Ticket t = new Ticket();
Thread t1 = new Thread(t);
Thread t2 = new Thread(t);
Thread t3 = new Thread(t);
Thread t4 = new Thread(t);
t1.start();
t2.start();
t3.start();
t4.start();
}
}
输出结果如下:
Thread-1sale...1
Thread-3sale...0
Thread-0sale...-1
Thread-2sale...-2
表示四个线程在while语句执行ticket--之前都进入到while方法体内。相当于while(ticket>0)的条件失去的作用。
作者:
王冰
时间:
2012-7-14 23:26
public void run()
{
while(ticket>0)//
假如当ticket=1时,t1进来
{
try
{
Thread.sleep(10);
//
t1执行到这里,暂停执行,t2进来,
这时ticket=1
,t2可以执行,
t2执行到这里,也暂停执行,t3进来
} //
由于这几个线程进来的时候
ticket=1
,
所以可以获得执行权
catch(Exception e)
{
}
System.out.println(Thread.currentThread().getName()+"sale..."+ticket--);//
如果t3继续执行到这里,就会卖1号票,1号票卖了后,
//
ticket--变为0,t3执行完放弃执行权,那么t2就会执行到这里
//
这样t2卖的票会变成0号,t2执行完之后,ticket--变为-1,t3继续执行到这里,那么t3
//
卖的票就会变成-1号,它们都不用继续去判断ticket是否大于零这个条件,故可以打印出来
/
这样就出现了安全问题
}
}
作者:
柯玲
时间:
2012-7-14 23:46
就假设ticket=1,有四个线程卖票,首先明确:(1)没有对共享数据加锁,任一线程只要拿到执行权都可以走到while语句里面
(2)sleep()的作用:释放CPU执行权,不释放锁,此案例无锁,当执行到sleep(long time)时,线程放弃CPU执行权
(3)ticket--动作是在sleep()之后执行的,当线程执行到sleep()被冻结以后,ticket的值还是为1.
(4)ticket--动作等同于ticket=ticket--,把ticket的值赋给左边以后,才自减一次
用以下较为极端的一个场景描述:
Thread-0拿到CPU执行权,到sleep(10)被冻结,被Thread-1抢到执行权;
Thread-1执行到sleep(10)也冻结,Thread-2抢到执行权;
Thread-2执行到sleep(10)冻结,Thread-3抢到执行权;
Thread-3执行到sleep(10)冻结;
假若Thread-3冻结以后,sleep()的时间才到,那么第一个被等待的线程Thread-0又重新拿到执行权,执行打印语句,打印为1
后面的相继醒过来,就出现了0,-1,-2
欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/)
黑马程序员IT技术论坛 X3.2