JUC之公平锁与非公平锁

ReentrantLock抢票案例

java 复制代码
class Ticket
{
    private int number = 30;
    ReentrantLock lock = new ReentrantLock();
    //ReentrantLock lock = new ReentrantLock(true);

    public void sale()
    {
        lock.lock();
        try
        {
            if(number > 0)
            {
                System.out.println(Thread.currentThread().getName()+"卖出第:\t"+(number--)+"\t 还剩下:"+number);
            }
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            lock.unlock();
        }
    }
}



public class SaleTicketDemo
{
    public static void main(String[] args)
    {
        Ticket ticket = new Ticket();

        new Thread(() -> { for (int i = 0; i <35; i++)  ticket.sale(); },"a").start();
        new Thread(() -> { for (int i = 0; i <35; i++)  ticket.sale(); },"b").start();
        new Thread(() -> { for (int i = 0; i <35; i++)  ticket.sale(); },"c").start();
    }
}

非公平锁演示:

b没有抢到票,基本都被c抢了。

非公平锁

  • 默认是非公平锁
  • 非公平锁可以插队,买卖票不均匀。
  • 是指多个线程获取锁的顺序并不是按照申请锁的顺序,有可能后申请 的线程比先申请的线程优先获取锁,在高并发环境下,有可能造成优先级翻转或饥饿的状态(某个线程一直得不到锁)

改成公平锁后的效果

java 复制代码
package com.sgm.springboottest.demos.web;

import java.util.concurrent.locks.ReentrantLock;

class Ticket
{
    private int number = 30;
//    ReentrantLock lock = new ReentrantLock();
    ReentrantLock lock = new ReentrantLock(true);

    public void sale()
    {
        lock.lock();
        try
        {
            if(number > 0)
            {
                System.out.println(Thread.currentThread().getName()+"卖出第:\t"+(number--)+"\t 还剩下:"+number);
            }
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            lock.unlock();
        }
    }
}



public class SaleTicketDemo
{
    public static void main(String[] args)
    {
        Ticket ticket = new Ticket();

        new Thread(() -> { for (int i = 0; i <35; i++)  ticket.sale(); },"a").start();
        new Thread(() -> { for (int i = 0; i <35; i++)  ticket.sale(); },"b").start();
        new Thread(() -> { for (int i = 0; i <35; i++)  ticket.sale(); },"c").start();
    }
}

abc均匀的抢到了票

公平锁

  • ReentrantLock lock = new ReentrantLock(true);
  • 买卖票一开始a占优,后面a b c a b c a b c均匀分布
  • 是指多个线程按照申请锁的顺序来获取锁,这里类似排队买票,先来的人先买后来的人在队尾排着,这是公平的

为什么会有公平锁/非公平锁的设计?为什么默认是非公平?

  • 恢复挂起的线程到真正锁的获取还是有时间差的,从开发人员来看这个时间微乎其微,但是从CPU的角度来看,这个时间差存在的还是很明显的。所以非公平锁能更充分的利用CPU 的时间片,尽量减少 CPU 空闲状态时间。

  • 使用多线程很重要的考量点是线程切换的开销,当采用非公平锁时,当1个线程请求锁获取同步状态,然后释放同步状态,因为不需要考虑是否还有前驱节点,所以刚释放锁的线程在此刻再次获取同步状态的概率就变得非常大,所以就减少了线程的开销。

什么时候用公平?什么时候用非公平?

如果为了更高的吞吐量 ,很显然非公平锁是比较合适的 ,因为节****省很多线程切换时间,吞吐量自然就上去了; 否则那就用公平锁,大家公平使用。

相关推荐
冉冰学姐19 小时前
基于ssm的技能比赛报名管理系统29817vn0(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面
java·数据库·spring·ssm 框架应用
代码雕刻家1 天前
3.5.Maven-依赖管理-依赖配置&依赖传递
java·maven
!chen1 天前
MyBatis-plus拓展之字段类型处理器、自动填充和乐观锁
java·tomcat·mybatis
Jin、yz1 天前
JAVA 八股
java·开发语言
va学弟1 天前
Java 网络通信编程(6):视频通话
java·服务器·网络·音视频
pjw198809031 天前
Spring Framework 中文官方文档
java·后端·spring
jgyzl1 天前
2026.3.11MyBatis-Plus基本使用与思考
java·数据库·mybatis
Full Stack Developme1 天前
Java 常用通信协议及对应的框架
java·开发语言
( •̀∀•́ )9201 天前
Spring Boot 启动报错 `BindException: Permission denied`
java·spring boot·后端
杰克尼1 天前
苍穹外卖--day10
java·数据库·spring boot·mybatis·notepad++