java同步锁售票_线程同步锁之火车站售票案例

前言:

谈到多线程,就不得不说线程同步,那么什么是线程同步?

线程同步

即当有一个线程在对内存进行操作时,其他线程都不可以对这个内存地址进行操作,直到该线程完成操作, 其他线程才能对该内存地址进行操作,而其他线程又处于等待状态,简单来说,就是一个线程在对内存进行操作,如修改一个对象,其他线程不能对该对象进行修改,等该线程执行完毕后,才能进行操作。实现线程同步的方法有很多,java中常用synchronized锁来实现。

下面用一个小demo来说明一下区别

-火车站有三个窗口进行售票,总共有100张票,窗口名分别:为窗口A,窗口B,窗口C

-每售出一张票耗时100毫秒,售出后打印出由哪个窗口售出且还剩多少张票.

a7157fc8ff68508ebf475f582041b851.png

运行结果

183f5645d02a91ab2df61d5d6434ba89.png

从结果可以看出,3个窗口卖多了一张票,这就是线程不同步出现的问题,从上面可以看出当还剩一张票时,ABC三个线程都拿到了这张票,然后都分别卖出去了,导致--操作发生了多次产生了负数,这在实际生活中显然 是不允许的,那么如何去解决?

synchronized锁可以将该操作锁起来,就比如你去卫生间,把门一关,别人就进不来了,只能等你把事情做完了,他才能进去。那么如何去实现?

7e2dfa3629cfd4dabc1d8f82dac7b841.png

只需在卖票的代码块上加上一个锁即可,注意的是多个线程拿到的锁对象必须相同,在这里我们直接使用了TicketsSeller.class,这个MyThread.class是一个全局唯一的,我们同样可以自定义一个静态变量来当作锁对象,只要保证多个线程拿到的是同一个对象即可。

要注意的是锁对象范围越大,性能越低,本次demo使用的串行效率也比较比,在实际开发中,如果不是严格要求一般不会用到

6d9ea1641399d1c8a4e15e0a64de94cb.png

当然锁并不是只有这一种,分很多种,下面简单介绍下锁的分类。具体的需要大家在实际开发中取接触,了解。

偏向锁、自旋锁、重量级锁

Java在使用synchronize关键字,首先在Java对象头进行markword,记录这个线程id,只有一个线程对这个对象加锁,这个锁叫做偏向锁。

偏向锁如果有线程争用,那么升级为自旋锁?一个锁如果被使用,那么另外一个线程打算争抢这把锁,则会陷入while循环,形成自旋。这叫做自旋锁。

旋10次之后,升级为重量级锁。重量级锁以OS为主体。那么重量级锁不会占用CPU。

注:锁不能降级

公平锁、非公平锁

公平锁:加锁之前先检查是否有排队等待的线程,有的话优先处理排前面的线程,先来先得。

非公平锁:线程加锁时直接尝试获取,获取不到就到队尾等待

非公平锁 Lock nonFairLock=new ReentrantLock(true);//默认空参是true

公平锁 Lock fairLock=new ReentrantLock(false);

注:非公平锁比公平锁快很多

7.3.重入锁

ReetranLock含义是重入锁,什么意思呢,可以进行加锁多次,和解锁多次,比如

77cc11f68c4e2e451cc91b26f6914010.png

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值