Java中线程的安全问题
2014-04-16 15:46
295 查看
假设我们现在要用代码实现这个场景:
售票处共有100张票,同时开设4个窗口同时售票,知道票售完为止
我们暂且将这种场景想象成线程的实现过程:四个线程同时售票,直到售完为止
使用Java API文档中线程使用的第一种方法,我们定义一个继承了Thread类的类Ticket,并重写run方法:
class Ticket extends Thread
{
private static int num=100;
public void sale()
{
while(true)
{
if(num>0)
{
System.out.println(Thread.currentThread().getName()+"Sale:"+num--);
}
if(num==0)
{
//Thread.currentThread().stop();
break;
}
}
}
public void run()
{
sale();
}
}
在main函数中实例化四个Ticket对象,并同时开启这四个线程
public static void main(String[] args)
{
Ticket t1=new Ticket();
Ticket t2=new Ticket();
Ticket t3=new Ticket();
Ticket t4=new Ticket();
t1.start();
t2.start();
t3.start();
t4.start();
}
运行代码,结果截图如下:
运行结果好像有些问题:为什么售票的顺序是错乱的呢?
问题的原因在于cmd也是一个程序,程序的执行是要依靠CPU的执行权,程序的运行是要靠CPU的不断切换执行权而运行的
在CPU在不同程序中不断的切换执行权的时候就会导致控制台结果输出的错乱。
好,排除了这个"异象",那程序的运行结果大概就是我们想要的结果了吧?从100递减到1,貌似没有什么问题。
现在我们在程序运行到run方法中的if(num>0)后让线程休息一段时间,将Ticket类改为以下代码:
class Ticket extends Thread
{
private static int num=100;
public void sale()
{
while(true)
{
if(num>0)
{
try
{
Thread.sleep(20);
}
catch (InterruptedException e)
{
System.out.println("Error:"+e);
}
System.out.println(Thread.currentThread().getName()+"Sale:"+num--);
}
if(num==0)
{
//Thread.currentThread().stop();
break;
}
}
}
public void run()
{
sale();
}
}
运行结果,就会出现如图所示的灵异现象:
程序的结果居然出现了负值?!就像你买到的火车票是负数座位一样令人毛骨损人!见鬼了吗??
前面我们说过,程序的执行是在CPU不断切换执行权的情况下实现的,当某些线程在执行进入if(){}结果内,
让线程sleep()一段时间,这时就有可能有其它线程在这段时间内也进入了if(num>0){}内,因为进入{}的都满足了num>0
的条件,然后等线程休息结束后得到了执行权继续往下执行,就会把num值变成负数,这也就是线程灵异现象的产生原因。
售票处共有100张票,同时开设4个窗口同时售票,知道票售完为止
我们暂且将这种场景想象成线程的实现过程:四个线程同时售票,直到售完为止
使用Java API文档中线程使用的第一种方法,我们定义一个继承了Thread类的类Ticket,并重写run方法:
class Ticket extends Thread
{
private static int num=100;
public void sale()
{
while(true)
{
if(num>0)
{
System.out.println(Thread.currentThread().getName()+"Sale:"+num--);
}
if(num==0)
{
//Thread.currentThread().stop();
break;
}
}
}
public void run()
{
sale();
}
}
在main函数中实例化四个Ticket对象,并同时开启这四个线程
public static void main(String[] args)
{
Ticket t1=new Ticket();
Ticket t2=new Ticket();
Ticket t3=new Ticket();
Ticket t4=new Ticket();
t1.start();
t2.start();
t3.start();
t4.start();
}
运行代码,结果截图如下:
运行结果好像有些问题:为什么售票的顺序是错乱的呢?
问题的原因在于cmd也是一个程序,程序的执行是要依靠CPU的执行权,程序的运行是要靠CPU的不断切换执行权而运行的
在CPU在不同程序中不断的切换执行权的时候就会导致控制台结果输出的错乱。
好,排除了这个"异象",那程序的运行结果大概就是我们想要的结果了吧?从100递减到1,貌似没有什么问题。
现在我们在程序运行到run方法中的if(num>0)后让线程休息一段时间,将Ticket类改为以下代码:
class Ticket extends Thread
{
private static int num=100;
public void sale()
{
while(true)
{
if(num>0)
{
try
{
Thread.sleep(20);
}
catch (InterruptedException e)
{
System.out.println("Error:"+e);
}
System.out.println(Thread.currentThread().getName()+"Sale:"+num--);
}
if(num==0)
{
//Thread.currentThread().stop();
break;
}
}
}
public void run()
{
sale();
}
}
运行结果,就会出现如图所示的灵异现象:
程序的结果居然出现了负值?!就像你买到的火车票是负数座位一样令人毛骨损人!见鬼了吗??
前面我们说过,程序的执行是在CPU不断切换执行权的情况下实现的,当某些线程在执行进入if(){}结果内,
让线程sleep()一段时间,这时就有可能有其它线程在这段时间内也进入了if(num>0){}内,因为进入{}的都满足了num>0
的条件,然后等线程休息结束后得到了执行权继续往下执行,就会把num值变成负数,这也就是线程灵异现象的产生原因。
相关文章推荐
- java线程冲突问题——不安全的线程例子
- java中如何解决线程不安全的问题呢?
- Java多线程中线程安全与锁问题
- java线程安全问题之静态变量、实例变量、局部变量
- java解决线程不安全问题的方法
- java之线程安全问题
- Java基础之线程安全问题
- java多线程(1):线程的创建和多线程的安全问题
- Java 线程通信的安全问题(同步)
- java线程安全问题之静态变量、实例变量、局部变量
- java线程安全问题笔记
- 利用JAVA线程安全队列简单实现读者写者问题。
- java 多线程(线程间通信-解决安全问题)
- JAVA中关于线程通信安全问题
- 一个简单的Java对象池实现——可用来解决SimpleDateFormat的线程安全问题
- Java线程安全问题
- java线程安全问题1
- 浅谈利用同步机制解决Java中的线程安全问题
- java线程安全问题之静态变量、实例变量、局部变量
- java线程安全问题原理性分析