线程安全问题产生的原因:
1、多个线程在操作共享数据;
2、操作共享数据的线程代码有多条(意思是代码块中的语句不止一条,容易在一个线程执行了一部分后停止,而其他线程继续执行还没来得及更新的数据);
解决方法一:使用同步代码块
下面是一个售票的代码
class Ticket implements Runnable
{
private int num=100;//总票数
public void run()
{
while(true)
{
if(num>0)
{
try{Thread.sleep(10);}
catch (InterruptedException e) { }
System.out.println(Thread.currentThread().getName()+"......sale....."+num--);
}
}
}
}
class TicketDemo
{
public static void main(String [] args)
{
Ticket t= new Ticket(); //新建一个Ticket对象;
Thread d1=new Thread(t);
Thread d2=new Thread(t); //d1和d2操作的都是同一个Ticket对象,里面的成员变量是共享的。
d1.start();
d2.start();
}
}
上面这段代码就容易发生安全问题,票可能会出到0号票,甚至-1号票。我们先用同步代码块来解决这个问题
class Ticket implements Runnable
{
private int num=100;//总票数
Object obj=new Object();//必须把对象定义在成员变量的位置上,这样才能保证只有一个跟踪对象,即只有一个锁。
public void run()
{
while(true)
{
synchronized(obj)
{
if(num>0)
{
try{Thread.sleep(10);}
catch (InterruptedException e) { }
System.out.println(Thread.currentThread().getName()+"......sale....."+num--);
}
}
}
}
}
也可以用同步函数解决上述问题
class Ticket implements Runnable
{
private int num=100;//总票数
public void run()
{
while(true)
{
if(num>0)
{
this.show;
}
}
public synchronized void show()//定义了同步函数,它的锁就是调用run方法的对象
{
try{Thread.sleep(10);}
catch (InterruptedException e) { }
System.out.println(Thread.currentThread().getName()+"......sale....."+num--);
}
}
}