如何解决多线程不安全

如何解决多线程不安全

比如买票,会出现一票多求,负票等问题

解决;
    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张票

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值