原标题:Java知识进阶-程序员必懂的自旋锁TicketLock原理-知识铺
知识铺: 致力于打造轻知识点,持续更新每次的知识点较少,阅读不累。不占太多时间,不停的来唤醒你记忆深处的知识点。
一、TicketLock 原理
内部维护的一个本地线程ThreadLocal变量,存放当前线程获取到的排队号。当获取服务的线程排队号和当前正在获取锁的线程服务排队号不相等时,就继续。
解决公平性: 解决之前普通CAS自旋锁(前面讲解过,手写一个自旋锁)等待线程会不停自旋,随机获取锁,导致先到的线程反而获取不到锁的公平性。
关键点1:queNum.getAndIncrement()
这个函数调用的是compareAndSet操作,把排队号queNum加上1, 而自己获取到的还是未添加的0 刚好和curNum=0 是一样,这个时候线程就获取到了锁。
(注意:这里比较像mysql中的主键,自增型,insert后获取到的是当前ID,但是mysql的自增起点已经+1啦)
后面的线程拿到的排队号 都会自动加上+1 和curNum=0 就不相等了,while一直为true,就被上锁了。
关键点2: curNum.compareAndSet(myid, next);
这句是保准公平性的关键之处,也是重中之重。 当前线程在释放锁的时候,会把自己的ID+1,直接释放给它后面紧靠近它的线程。
关键点3: AtomicInteger
保准原子性关键之处,这里使用的是它的getAndIncrement函数,这个函数特点返回的是添加前的排队号,而又把后期的排队号给加上了1。
关键点4: compareAndSet
compareAndSet 这个方法的实现如下:
Unsafe 类 ,实现了CAS操作的C++类,从最底层保准了CAS操作。
二、 优缺点
优点: 公平性,解决了访问顺序问题。
缺点: 如果是cpu多核的服务器,在获取排队号的时候,必须从主存中读取,并阻止其他cpu修改。返回搜狐,查看更多
责任编辑: