比如买票,会出现一票多求,负票等问题
解决;
java提供了一个同步机制(同步锁):synchronized :包装其中的多条语句
例:
synchronized(对象){
多条语句对共享语句进行操作
}
对象:需要使用同一个对象,封装到外面
注意:任意对象,但必须创建,也必须存在
线程安全的检测条件:
1)看我们当前的环境是否属于多线程程序
2)当前的多线程程序中是否有共享数据
3)是否多条语句对共性数据进行操作
需求:
模拟电影院售票案例,现有100张票,三家影院同时出售,卖出每张票中间会有100毫秒的延迟
代码:
public class SellTickets implements Runnable {
//定义票数
private int tickets = 1;
Demo d = new Demo();
@Override
public void run() {
while(tickets<=100){
//同步锁
synchronized(d){
if(tickets<=100){
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+":"+"正在出售第"+(tickets++)+"张票");
}
}
}
}
}
class Demo{}
public static void main(String[] args) {
SellTickets st = new SellTickets();
//创建线程对象
Thread th1 = new Thread(st, "窗口一");
Thread th2 = new Thread(st, "窗口二");
Thread th3 = new Thread(st, "窗口三");
//启动线程
th1.start();
th2.start();
th3.start();
}
结果:
窗口一:正在出售第1张票
窗口一:正在出售第2张票
窗口一:正在出售第3张票
窗口三:正在出售第4张票
窗口三:正在出售第5张票
窗口二:正在出售第6张票
窗口二:正在出售第7张票
窗口三:正在出售第8张票
窗口三:正在出售第9张票
窗口一:正在出售第10张票
窗口一:正在出售第11张票
窗口三:正在出售第12张票
窗口二:正在出售第13张票
窗口二:正在出售第14张票
窗口三:正在出售第15张票
窗口三:正在出售第16张票
窗口一:正在出售第17张票
窗口一:正在出售第18张票
窗口一:正在出售第19张票
窗口三:正在出售第20张票
窗口三:正在出售第21张票
窗口三:正在出售第22张票
窗口三:正在出售第23张票
窗口三:正在出售第24张票
窗口三:正在出售第25张票
窗口三:正在出售第26张票
窗口三:正在出售第27张票
窗口二:正在出售第28张票
窗口二:正在出售第29张票
窗口二:正在出售第30张票
窗口三:正在出售第31张票
窗口三:正在出售第32张票
窗口三:正在出售第33张票
窗口三:正在出售第34张票
窗口一:正在出售第35张票
窗口三:正在出售第36张票
窗口二:正在出售第37张票
窗口三:正在出售第38张票
窗口三:正在出售第39张票
窗口三:正在出售第40张票
窗口三:正在出售第41张票
窗口三:正在出售第42张票
窗口一:正在出售第43张票
窗口三:正在出售第44张票
窗口三:正在出售第45张票
窗口三:正在出售第46张票
窗口三:正在出售第47张票
窗口三:正在出售第48张票
窗口三:正在出售第49张票
窗口三:正在出售第50张票
窗口二:正在出售第51张票
窗口二:正在出售第52张票
窗口二:正在出售第53张票
窗口二:正在出售第54张票
窗口二:正在出售第55张票
窗口三:正在出售第56张票
窗口一:正在出售第57张票
窗口一:正在出售第58张票
窗口三:正在出售第59张票
窗口三:正在出售第60张票
窗口三:正在出售第61张票
窗口三:正在出售第62张票
窗口三:正在出售第63张票
窗口三:正在出售第64张票
窗口三:正在出售第65张票
窗口二:正在出售第66张票
窗口三:正在出售第67张票
窗口三:正在出售第68张票
窗口三:正在出售第69张票
窗口三:正在出售第70张票
窗口三:正在出售第71张票
窗口三:正在出售第72张票
窗口三:正在出售第73张票
窗口三:正在出售第74张票
窗口一:正在出售第75张票
窗口三:正在出售第76张票
窗口三:正在出售第77张票
窗口三:正在出售第78张票
窗口三:正在出售第79张票
窗口三:正在出售第80张票
窗口二:正在出售第81张票
窗口三:正在出售第82张票
窗口一:正在出售第83张票
窗口三:正在出售第84张票
窗口三:正在出售第85张票
窗口二:正在出售第86张票
窗口二:正在出售第87张票
窗口三:正在出售第88张票
窗口三:正在出售第89张票
窗口一:正在出售第90张票
窗口一:正在出售第91张票
窗口三:正在出售第92张票
窗口三:正在出售第93张票
窗口二:正在出售第94张票
窗口三:正在出售第95张票
窗口一:正在出售第96张票
窗口一:正在出售第97张票
窗口三:正在出售第98张票
窗口二:正在出售第99张票
窗口二:正在出售第100张票
使用同步机制解决了线程的安全问题,但是我们并没有看到具体的锁对象是谁,JDK5以后java提供了接口Lock,里面又提供了一些方法:
public void lock()获取锁
public void unlock():释放锁
Lock 实现提供了比使用 synchronized 方法和语句可获得的更广泛的锁定操作
由于该Lock接口不能实例化,提供了子实现类:ReentrantLock
代码:
public class MyLock implements Runnable{
private int tickets = 1;
//创建锁对象
Lock l = new ReentrantLock();
@Override
public void run() {
while(tickets <= 100){
l.lock();
if(tickets<=100){
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+":"+"正在出售第"+(tickets++)+"张票");
}
l.unlock();
}
}
}
public static void main(String[] args) {
MyLock ml = new MyLock();
//创建多线程对象
Thread th1 = new Thread(ml, "窗口一");
Thread th2 = new Thread(ml, "窗口二");
Thread th3 = new Thread(ml, "窗口三");
th1.start();
th2.start();
th3.start();
}
结果:
窗口一:正在出售第1张票
窗口二:正在出售第2张票
窗口二:正在出售第3张票
窗口二:正在出售第4张票
窗口二:正在出售第5张票
窗口二:正在出售第6张票
窗口二:正在出售第7张票
窗口二:正在出售第8张票
窗口二:正在出售第9张票
窗口二:正在出售第10张票
窗口二:正在出售第11张票
窗口三:正在出售第12张票
窗口一:正在出售第13张票
窗口二:正在出售第14张票
窗口三:正在出售第15张票
窗口一:正在出售第16张票
窗口二:正在出售第17张票
窗口二:正在出售第18张票
窗口二:正在出售第19张票
窗口三:正在出售第20张票
窗口三:正在出售第21张票
窗口三:正在出售第22张票
窗口一:正在出售第23张票
窗口二:正在出售第24张票
窗口二:正在出售第25张票
窗口二:正在出售第26张票
窗口二:正在出售第27张票
窗口二:正在出售第28张票
窗口二:正在出售第29张票
窗口二:正在出售第30张票
窗口三:正在出售第31张票
窗口三:正在出售第32张票
窗口一:正在出售第33张票
窗口二:正在出售第34张票
窗口三:正在出售第35张票
窗口一:正在出售第36张票
窗口二:正在出售第37张票
窗口二:正在出售第38张票
窗口二:正在出售第39张票
窗口二:正在出售第40张票
窗口二:正在出售第41张票
窗口二:正在出售第42张票
窗口二:正在出售第43张票
窗口二:正在出售第44张票
窗口二:正在出售第45张票
窗口二:正在出售第46张票
窗口二:正在出售第47张票
窗口三:正在出售第48张票
窗口三:正在出售第49张票
窗口三:正在出售第50张票
窗口三:正在出售第51张票
窗口三:正在出售第52张票
窗口一:正在出售第53张票
窗口二:正在出售第54张票
窗口二:正在出售第55张票
窗口二:正在出售第56张票
窗口三:正在出售第57张票
窗口三:正在出售第58张票
窗口一:正在出售第59张票
窗口二:正在出售第60张票
窗口二:正在出售第61张票
窗口二:正在出售第62张票
窗口二:正在出售第63张票
窗口二:正在出售第64张票
窗口二:正在出售第65张票
窗口二:正在出售第66张票
窗口二:正在出售第67张票
窗口二:正在出售第68张票
窗口二:正在出售第69张票
窗口二:正在出售第70张票
窗口三:正在出售第71张票
窗口一:正在出售第72张票
窗口二:正在出售第73张票
窗口二:正在出售第74张票
窗口二:正在出售第75张票
窗口二:正在出售第76张票
窗口二:正在出售第77张票
窗口二:正在出售第78张票
窗口二:正在出售第79张票
窗口二:正在出售第80张票
窗口二:正在出售第81张票
窗口二:正在出售第82张票
窗口二:正在出售第83张票
窗口二:正在出售第84张票
窗口二:正在出售第85张票
窗口二:正在出售第86张票
窗口二:正在出售第87张票
窗口二:正在出售第88张票
窗口二:正在出售第89张票
窗口二:正在出售第90张票
窗口二:正在出售第91张票
窗口二:正在出售第92张票
窗口二:正在出售第93张票
窗口二:正在出售第94张票
窗口二:正在出售第95张票
窗口二:正在出售第96张票
窗口二:正在出售第97张票
窗口三:正在出售第98张票
窗口一:正在出售第99张票
窗口二:正在出售第100张票