本片博客给大家通过模拟卖票问题讲解线程安全问题
1、多个线程模拟卖票问题
public class SaleTicket extends Thread{
//非静态属性归每个对象所有,静态属性归所有对象所有
private static int ticket = 100;
public void run() {
while(ticket > 0) {
try {
Thread.sleep(20);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(getName() + "卖了1张票,还剩" + (ticket) + "张票");
}
}
}
public class TestSaleTicket {
public static void main(String[] args) {
SaleTicket s1 = new SaleTicket();
s1.setName("火车站:");
SaleTicket s2 = new SaleTicket();
s2.setName("代售点:");
SaleTicket s3 = new SaleTicket();
s3.setName("网络:");
s1.start();
s2.start();
s3.start();
}
}
产生线程安全问题的根本原因
- 1.必须有单线程环境
- 2.必须有共享数据
- 3.多个线程对共享数据进行修改
2、两种方式解决线程安全问题
方式一.使用同步代码块,需要一把指定的代码锁,任意对象都可以当锁
语法格式
synchronized(锁对象){需要同步的代码(锁住的代码)}
public class SaleTicket extends Thread{
//非静态属性归每个对象所有,静态属性归所有对象所有
private static int ticket = 100;
private static Object object = new Object();//锁对象,要保证多个线程共享同一把锁
public void run() {
synchronized (object) {
while(ticket > 0) {
try {
Thread.sleep(20);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(getName() + "卖了1张票,还剩" + (--ticket) + "张票");
}
}
}
}
方式二2.同步方法,就是在方法上添加synchronized关键字即可
- 1)对于非静态方法,锁是this
- 2)对于静态方法,锁是类
public class SaleTicket implements Runnable{
//非静态属性归每个对象所有,静态属性归所有对象所有
private static int ticket = 100;
public synchronized void run() {
while(ticket > 0) {
try {
Thread.sleep(20);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.cu