多线程售票(用synchronized锁、ReentrantLock锁解决多线程数据安全问题)

标题(多个)三个线程售票100或者更(少)多(线程安全问题)

1. 创建售票类SellTicket并继承Runnable接口

  • 使用synchronized锁
public class SellTicket implements  Runnable{
    private int tickets=100;//定义成员变量 有一百张票
    private Object obj=new Object();//创建对象锁
    @Override
    public void run() {
        while(true) {//死循环 一直会有人来买票 询问
            synchronized (obj) {//锁多条语句共享操作
                if (tickets > 0) {//当票数大于0
                	
   						try {
                            Thread.sleep(100);//模仿卖票消耗时间
                            System.out.println(Thread.currentThread().getName() + "正在出售第" + tickets + "张,还剩余"+(100-tickets)+"张票");
                            tickets--;
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                }
            }
        }
    }
}
  • 使用ReentrantLock锁
public class SellTicket implements Runnable {
    private static int tickets = 100;
    private Lock lock=new ReentrantLock();//实例化重入锁
     @Override
    public void run() {
        while (true) {
                lock.lock();//显性加锁
                    if (tickets > 0) {
                        try {
                            Thread.sleep(100);
                            System.out.println(Thread.currentThread().getName() + "正在出售第" + tickets + "张票");
                            tickets--;
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }finally {
                            lock.unlock();//显性释放锁
                        }


                    }

                }

            }
          }  

2. 创建测试类SellTicketDemo

public class SellTicketDemo {
    public static void main(String[] args) {
        SellTicket s=new SellTicket();//创建售票对象
        //把售票对象作为构造方法参数传递
        Thread st1 = new Thread(s,"售票窗口一");
        Thread st2 = new Thread(s,"售票窗口二");
        Thread st3 = new Thread(s,"售票窗口三");
        //启动线程
        st1.start();
        st2.start();
        st3.start();

    }
}

3. 运行结果:

售票窗口二正在出售第100张票,还剩余0张票
售票窗口二正在出售第99张票,还剩余1张票
售票窗口二正在出售第98张票,还剩余2张票
售票窗口二正在出售第97张票,还剩余3张票
售票窗口二正在出售第96张票,还剩余4张票
售票窗口二正在出售第95张票,还剩余5张票
售票窗口二正在出售第94张票,还剩余6张票
售票窗口二正在出售第93张票,还剩余7张票
售票窗口二正在出售第92张票,还剩余8张票
售票窗口二正在出售第91张票,还剩余9张票
售票窗口二正在出售第90张票,还剩余10张票
售票窗口二正在出售第89张票,还剩余11张票
售票窗口二正在出售第88张票,还剩余12张票
售票窗口二正在出售第87张票,还剩余13张票
售票窗口二正在出售第86张票,还剩余14张票
售票窗口二正在出售第85张票,还剩余15张票
售票窗口二正在出售第84张票,还剩余16张票
售票窗口二正在出售第83张票,还剩余17张票
售票窗口二正在出售第82张票,还剩余18张票
售票窗口二正在出售第81张票,还剩余19张票
售票窗口二正在出售第80张票,还剩余20张票
售票窗口二正在出售第79张票,还剩余21张票
售票窗口二正在出售第78张票,还剩余22张票
售票窗口二正在出售第77张票,还剩余23张票
售票窗口二正在出售第76张票,还剩余24张票
售票窗口二正在出售第75张票,还剩余25张票
售票窗口二正在出售第74张票,还剩余26张票
售票窗口三正在出售第73张票,还剩余27张票
售票窗口三正在出售第72张票,还剩余28张票
售票窗口三正在出售第71张票,还剩余29张票
售票窗口三正在出售第70张票,还剩余30张票
售票窗口三正在出售第69张票,还剩余31张票
售票窗口三正在出售第68张票,还剩余32张票
售票窗口三正在出售第67张票,还剩余33张票
售票窗口三正在出售第66张票,还剩余34张票
售票窗口三正在出售第65张票,还剩余35张票
售票窗口三正在出售第64张票,还剩余36张票
售票窗口三正在出售第63张票,还剩余37张票
售票窗口三正在出售第62张票,还剩余38张票
售票窗口三正在出售第61张票,还剩余39张票
售票窗口三正在出售第60张票,还剩余40张票
售票窗口三正在出售第59张票,还剩余41张票
售票窗口三正在出售第58张票,还剩余42张票
售票窗口三正在出售第57张票,还剩余43张票
售票窗口三正在出售第56张票,还剩余44张票
售票窗口三正在出售第55张票,还剩余45张票
售票窗口三正在出售第54张票,还剩余46张票
售票窗口三正在出售第53张票,还剩余47张票
售票窗口三正在出售第52张票,还剩余48张票
售票窗口三正在出售第51张票,还剩余49张票
售票窗口三正在出售第50张票,还剩余50张票
售票窗口三正在出售第49张票,还剩余51张票
售票窗口三正在出售第48张票,还剩余52张票
售票窗口三正在出售第47张票,还剩余53张票
售票窗口三正在出售第46张票,还剩余54张票
售票窗口三正在出售第45张票,还剩余55张票
售票窗口三正在出售第44张票,还剩余56张票
售票窗口三正在出售第43张票,还剩余57张票
售票窗口三正在出售第42张票,还剩余58张票
售票窗口三正在出售第41张票,还剩余59张票
售票窗口三正在出售第40张票,还剩余60张票
售票窗口三正在出售第39张票,还剩余61张票
售票窗口三正在出售第38张票,还剩余62张票
售票窗口三正在出售第37张票,还剩余63张票
售票窗口三正在出售第36张票,还剩余64张票
售票窗口三正在出售第35张票,还剩余65张票
售票窗口三正在出售第34张票,还剩余66张票
售票窗口三正在出售第33张票,还剩余67张票
售票窗口三正在出售第32张票,还剩余68张票
售票窗口三正在出售第31张票,还剩余69张票
售票窗口三正在出售第30张票,还剩余70张票
售票窗口三正在出售第29张票,还剩余71张票
售票窗口三正在出售第28张票,还剩余72张票
售票窗口三正在出售第27张票,还剩余73张票
售票窗口三正在出售第26张票,还剩余74张票
售票窗口三正在出售第25张票,还剩余75张票
售票窗口三正在出售第24张票,还剩余76张票
售票窗口三正在出售第23张票,还剩余77张票
售票窗口三正在出售第22张票,还剩余78张票
售票窗口三正在出售第21张票,还剩余79张票
售票窗口三正在出售第20张票,还剩余80张票
售票窗口三正在出售第19张票,还剩余81张票
售票窗口三正在出售第18张票,还剩余82张票
售票窗口三正在出售第17张票,还剩余83张票
售票窗口三正在出售第16张票,还剩余84张票
售票窗口三正在出售第15张票,还剩余85张票
售票窗口三正在出售第14张票,还剩余86张票
售票窗口三正在出售第13张票,还剩余87张票
售票窗口三正在出售第12张票,还剩余88张票
售票窗口三正在出售第11张票,还剩余89张票
售票窗口三正在出售第10张票,还剩余90张票
售票窗口三正在出售第9张票,还剩余91张票
售票窗口一正在出售第8张票,还剩余92张票
售票窗口一正在出售第7张票,还剩余93张票
售票窗口一正在出售第6张票,还剩余94张票
售票窗口一正在出售第5张票,还剩余95张票
售票窗口一正在出售第4张票,还剩余96张票
售票窗口一正在出售第3张票,还剩余97张票
售票窗口一正在出售第2张票,还剩余98张票
售票窗口一正在出售第1张票,还剩余99张票

4. 两个锁的区别Synchronized、ReentrantLock

Java 中的并发锁大致分为隐式锁和显式锁两种。隐式锁就是synchronized ,显式锁主要包含两个接口:Lock 和 ReadWriteLock,主要实现类分别为ReentrantLock 和 ReentrantReadWriteLock,这两个类都是基于AQS(AbstractQueuedSynchronizer) 实现的。
synchronized 和 ReentrantLock 区别是什么?

  • ReentrantLock是Java中的课重入锁的一种实现,一次只能有一个线程持有锁,也就是独占锁的概念包含三个内内部类:Sync、NonFairSync、FairSync,公平性锁和非公平性锁通过构造函数来指定。

  • Synchronized修饰的方法或者代码块相当于并发中的临界区,在同一时刻JVM只允许一个线程进入执行。synchronized通过锁机制来达到同一时刻只允许一个线程进入执行的效果,在并发编程中,Synchronized锁机制可以做到线程并发的原子性,有序性,可见性。

① synchronized 在竞争锁的时候会一直等待;ReentrantLock 可以尝试获取锁(tryLock()),也可以获取结果。
②synchronized获取锁时不能设置超时时间;ReentrantLock 可以设置获取锁的超时时间 用方法tryLock(long time, TimeUnit unit)在一定时间内尝试性的获取锁,如果锁在给定的等待时间内空闲,并且当前的线程未被中断,则可以获取锁,如果锁可用,则立即获取锁,返回true,如果锁不可用,则返回false;
③synchronized无法实现公平锁;ReentrantLock 可以实现公平锁,即先等待先获取到锁 (Lock类转换为公平锁FairLock,原理是:每一个Lock调用的线程都会进入到队列,当解锁后,只有队列中的第一个线程被允许获取锁)
④synchronized 控制等待和唤醒需要结合加锁对象的wait() 和 notify()、notifyAll();ReentrantLock 控制等待和唤醒需要结合 Condition 的
await() 和 signal()、signalAll() 方法
⑤ synchronized 是 JVM层面实现的;ReentrantLock 是 JDK 代码层面实现
⑥synchronized在加锁代码块或方法执行完或者出现异常,会自动释放锁;ReentrantLock 不会自动释放锁,需要在 finally{} 代码块显示释放比如上面代码 }finally {
lock.unlock();//显性释放锁
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值