多线程(线程安全问题)

这里以买票为例:

继承Thread的第一种创建线程的方法,不易满足多个线程共享一块数据资源的需求。

所以采用实现Runnable接口的第二种方法来创建线程。

class Ticket implements Runnable{

private int num = 100;
public void run() {
sale();
}

public void sale (){
while(true){
if(num > 0)
{
try{Thread.sleep(10);}catch(InterruptedException e){}
System.out.println(Thread.currentThread().getName()+"****"+num);
num --;
}

}
}
}

class ThreadDemo {

public static void main (String[] arg){

Ticket d = new Ticket();

Thread t1= new Thread(d);
Thread t2 = new Thread(d);
Thread t3 = new Thread(d);
Thread t4 = new Thread(d);

t1.start();
t2.start();
t3.start();
t4.start();


}
}

看似没有问题实际是有线程问题的;

仔细分析下面这段代码:

cup是随机指向不同的线程,当t1线程刚进入if的代码块,还没有执行System输出语句,这是cup指向了t2,这个时候t2也会进入到if代码块,,t3,t4一样的道理。

此时,每个线程都可以执行System的买票代码,这样num就会小于0;

if(num > 0)
{
try{Thread.sleep(10);}catch(InterruptedException e){}//为了模式线程问题的场景
System.out.println(Thread.currentThread().getName()+"****"+num);
num --;
}

解决线程问题的方法:同步代码块。

synchronized(对象){}//这个对象类似于一个开关,没有线程进入代码块开关是开,有线程进入代码块开关是关,别的线程智能等待。

class Ticket implements Runnable{

private int num = 100;
Object obj = new Object();
public void run() {
sale();
}

public void sale (){
while(true){
synchronized(obj){
if(num > 0)
{
try{Thread.sleep(10);}catch(InterruptedException e){}
System.out.println(Thread.currentThread().getName()+"****"+num);
num --;
}
}

这样就解决了线程安全的问题。

}
}
}

线程安全问题产生的原因:

1.多个线程操作共享的数据。

2.操作共享数据的线程代码有多条。

同步的好处和弊端:

好处:解决线程安全问题。

弊端:相对降低了执行cpu效率,因为外部的线程都会判断同步锁无效。

同步的前提:多个线程必须使用的是同一个锁,就是synchronized(对象)的对象。

 

posted @ 2018-07-04 09:23  仙人掌的成长  阅读(114)  评论(0编辑  收藏  举报