公平锁和非公平锁介绍,为什么要“非公平”?

2023-05-16

什么是公平和非公平

公平锁指的是按照线程请求的顺序,来分配锁;而非公平锁指的是不完全按照请求的顺序,在一定情况下,可以允许插队。但需要注意这里的非公平并不是指完全的随机,不是说线程可以任意插队,而是仅仅“在合适的时机”插队

什么时候是合适的时机呢?

假设当前线程在请求获取锁的时候,恰巧前一个持有锁的线程释放了这把锁,那么当前申请锁的线程就可以不顾已经等待的线程而选择立刻插队。但是如果当前线程请求的时候,前一个线程并没有在那一时刻释放锁,那么当前线程还是一样会进入等待队列

为什么要设置非公平策略呢?

我们都知道非公平是 ReentrantLock的默认策略,如果我们不加以设置的话默认就是非公平的,难道我的这些排队的时间都白白浪费了吗,为什么别人比我有优先权呢?毕竟公平是一种很好的行为,而非公平是一种不好的行为

让我们考虑一种情况,假设线程 A 持有一把锁,线程 B 请求这把锁,由于线程 A 已经持有这把锁了,所以线程 B 会陷入等待,在等待的时候线程 B 会被挂起,也就是进入阻塞状态,那么当线程 A 释放锁的时候,本该轮到线程 B 苏醒获取锁,但如果此时突然有一个线程 C 插队请求这把锁,那么根据非公平的策略,会把这把锁给线程 C,这是因为唤醒线程 B 是需要很大开销的,很有可能在唤醒之前,线程 C 已经拿到了这把锁并且执行完任务释放了这把锁。相比于等待唤醒线程 B 的漫长过程,插队的行为会让线程 C 本身跳过陷入阻塞的过程,如果在锁代码中执行的内容不多的话,线程 C 就可以很快完成任务,并且在线程 B 被完全唤醒之前,就把这个锁交出去,这样是一个双赢的局面,对于线程 C 而言,不需要等待提高了它的效率,而对于线程 B 而言,它获得锁的时间并没有推迟,因为等它被唤醒的时候,线程 C 早就释放锁了,因为线程 C 的执行速度相比于线程 B 的唤醒速度,是很快的,所以 Java 设计非公平锁,是为了提高整体的运行效率

公平的场景

用图示来说明公平和非公平的场景,先来看公平的情况。假设我们创建了一个公平锁,此时有 4 个线程按顺序来请求公平锁,线程 1 在拿到这把锁之后,线程 2、3、4 会在等待队列中开始等待,然后等线程 1 释放锁之后,线程 2、3、4 会依次去获取这把锁,线程 2 先获取到的原因是它等待的时间最长

不公平的场景

假设线程 1 在解锁的时候,突然有线程 5 尝试获取这把锁,那么根据我们的非公平策略,线程 5 是可以拿到这把锁的,尽管它没有进入等待队列,而且线程 2、3、4 等待的时间都比线程 5 要长,但是从整体效率考虑,这把锁此时还是会交给线程 5 持有

代码演示公平和非公平

/**
 * 描述:演示公平锁,分别展示公平和不公平的情况,非公平锁会让现在持有锁的线程优先再次获取到锁
 */
public class FairAndUnfair {


    public static void main(String args[]) {
        PrintQueue printQueue = new PrintQueue();


        Thread thread[] = new Thread[10];
        for (int i = 0; i < 10; i++) {
            thread[i] = new Thread(new Job(printQueue), "Thread " + i);
        }


        for (int i = 0; i < 10; i++) {
            thread[i].start();
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }


}


class Job implements Runnable {


    private PrintQueue printQueue;


    public Job(PrintQueue printQueue) {
        this.printQueue = printQueue;
    }


    @Override
    public void run() {
        System.out.printf("%s: Going to print a job\n", Thread.currentThread().getName());
        printQueue.printJob(new Object());
        System.out.printf("%s: The document has been printed\n", Thread.currentThread().getName());
    }


}


class PrintQueue {


    private final Lock queueLock = new ReentrantLock(false);


    public void printJob(Object document) {
        queueLock.lock();


        try {
            Long duration = (long) (Math.random() * 10000);
            System.out.printf("%s: PrintQueue: Printing a Job during %d seconds\n",
                    Thread.currentThread().getName(), (duration / 1000));
            Thread.sleep(duration);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            queueLock.unlock();
        }


        queueLock.lock();
        try {
            Long duration = (long) (Math.random() * 10000);
            System.out.printf("%s: PrintQueue: Printing a Job during %d seconds\n",
                    Thread.currentThread().getName(), (duration / 1000));
            Thread.sleep(duration);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            queueLock.unlock();
            }
    }
}

可以通过改变 new ReentrantLock(false) 中的参数来设置公平/非公平锁,以上代码在公平的情况下的输出

Thread 0: Going to print a job
Thread 0: PrintQueue: Printing a Job during 5 seconds
Thread 1: Going to print a job
Thread 2: Going to print a job
Thread 3: Going to print a job
Thread 4: Going to print a job
Thread 5: Going to print a job
Thread 6: Going to print a job
Thread 7: Going to print a job
Thread 8: Going to print a job
Thread 9: Going to print a job
Thread 1: PrintQueue: Printing a Job during 3 seconds
Thread 2: PrintQueue: Printing a Job during 4 seconds
Thread 3: PrintQueue: Printing a Job during 3 seconds
Thread 4: PrintQueue: Printing a Job during 9 seconds
Thread 5: PrintQueue: Printing a Job during 5 seconds
Thread 6: PrintQueue: Printing a Job during 7 seconds
Thread 7: PrintQueue: Printing a Job during 3 seconds
Thread 8: PrintQueue: Printing a Job during 9 seconds
Thread 9: PrintQueue: Printing a Job during 5 seconds
Thread 0: PrintQueue: Printing a Job during 8 seconds
Thread 0: The document has been printed
Thread 1: PrintQueue: Printing a Job during 1 seconds
Thread 1: The document has been printed
Thread 2: PrintQueue: Printing a Job during 8 seconds
Thread 2: The document has been printed
Thread 3: PrintQueue: Printing a Job during 2 seconds
Thread 3: The document has been printed
Thread 4: PrintQueue: Printing a Job during 0 seconds
Thread 4: The document has been printed
Thread 5: PrintQueue: Printing a Job during 7 seconds
Thread 5: The document has been printed
Thread 6: PrintQueue: Printing a Job during 3 seconds
Thread 6: The document has been printed
Thread 7: PrintQueue: Printing a Job during 9 seconds
Thread 7: The document has been printed
Thread 8: PrintQueue: Printing a Job during 5 seconds
Thread 8: The document has been printed
Thread 9: PrintQueue: Printing a Job during 9 seconds
Thread 9: The document has been printed

而以上代码在非公平的情况下的输出是这样的

Thread 0: Going to print a job
Thread 0: PrintQueue: Printing a Job during 6 seconds
Thread 1: Going to print a job
Thread 2: Going to print a job
Thread 3: Going to print a job
Thread 4: Going to print a job
Thread 5: Going to print a job
Thread 6: Going to print a job
Thread 7: Going to print a job
Thread 8: Going to print a job
Thread 9: Going to print a job
Thread 0: PrintQueue: Printing a Job during 8 seconds
Thread 0: The document has been printed
Thread 1: PrintQueue: Printing a Job during 9 seconds
Thread 1: PrintQueue: Printing a Job during 8 seconds
Thread 1: The document has been printed
Thread 2: PrintQueue: Printing a Job during 6 seconds
Thread 2: PrintQueue: Printing a Job during 4 seconds
Thread 2: The document has been printed
Thread 3: PrintQueue: Printing a Job during 9 seconds
Thread 3: PrintQueue: Printing a Job during 8 seconds
Thread 3: The document has been printed
Thread 4: PrintQueue: Printing a Job during 4 seconds
Thread 4: PrintQueue: Printing a Job during 2 seconds
Thread 4: The document has been printed
Thread 5: PrintQueue: Printing a Job during 2 seconds
Thread 5: PrintQueue: Printing a Job during 5 seconds
Thread 5: The document has been printed
Thread 6: PrintQueue: Printing a Job during 2 seconds
Thread 6: PrintQueue: Printing a Job during 6 seconds
Thread 6: The document has been printed
Thread 7: PrintQueue: Printing a Job during 6 seconds
Thread 7: PrintQueue: Printing a Job during 4 seconds
Thread 7: The document has been printed
Thread 8: PrintQueue: Printing a Job during 3 seconds
Thread 8: PrintQueue: Printing a Job during 6 seconds
Thread 8: The document has been printed
Thread 9: PrintQueue: Printing a Job during 3 seconds
Thread 9: PrintQueue: Printing a Job during 5 seconds
Thread 9: The document has been printed

可以看出,非公平情况下,存在抢锁“插队”的现象,比如Thread 0 在释放锁后又能优先获取到锁,虽然此时在等待队列中已经有 Thread 1 ~ Thread 9 在排队了

公平和非公平的优缺点

 优势劣势
公平锁各线程公平平等,每一个线程在等待一段时间后,总有执行的机会更慢,吞吐量更少
非公平锁更快,吞吐量更大有可能产生线程饥饿,也就是某些线程在长时间内,始终得不到执行

源码分析

下面我们来分析公平和非公平锁的源码,具体看下它们是怎样实现的,可以看到在 ReentrantLock 类包含一个 Sync 类,这个类继承自AQS(AbstractQueuedSynchronizer),代码如下

public class ReentrantLock implements Lock, java.io.Serializable {
 
private static final long serialVersionUID = 7373984872572414699L;
 
/** Synchronizer providing all implementation mechanics */
 
private final Sync sync;

Sync 类的代码

abstract static class Sync extends AbstractQueuedSynchronizer {...}

Sync 有公平锁 FairSync 和非公平锁 NonfairSync两个子类

static final class NonfairSync extends Sync {...}
static final class FairSync extends Sync {...}

公平锁的锁获取源码如下

protected final boolean tryAcquire(int acquires) {
    final Thread current = Thread.currentThread();
    int c = getState();
    if (c == 0) {
        if (!hasQueuedPredecessors() && //这里判断了 hasQueuedPredecessors()
                compareAndSetState(0, acquires)) {
            setExclusiveOwnerThread(current);
            return true;
        }
    } else if (current == getExclusiveOwnerThread()) {
        int nextc = c + acquires;
        if (nextc < 0) {
            throw new Error("Maximum lock count exceeded");
        }
        setState(nextc);
        return true;
    }
    return false;
}

非公平锁的锁获取源码如下

final boolean nonfairTryAcquire(int acquires) {
    final Thread current = Thread.currentThread();
    int c = getState();
    if (c == 0) {
        if (compareAndSetState(0, acquires)) { //这里没有判断 hasQueuedPredecessors()
            setExclusiveOwnerThread(current);
            return true;
        }
    }
    else if (current == getExclusiveOwnerThread()) {
        int nextc = c + acquires;
        if (nextc < 0) // overflow
        throw new Error("Maximum lock count exceeded");
        setState(nextc);
        return true;
    }
    return false;
}

通过对比,我们可以明显的看出公平锁与非公平锁的 lock() 方法唯一的区别就在于公平锁在获取锁时多了一个限制条件hasQueuedPredecessors() 为 false,这个方法就是判断在等待队列中是否已经有线程在排队了。这也就是公平锁和非公平锁的核心区别,如果是公平锁,那么一旦已经有线程在排队了,当前线程就不再尝试获取锁;对于非公平锁而言,无论是否已经有线程在排队,都会尝试获取一下锁,获取不到的话,再去排队

注意:针对 tryLock() 方法,它不遵守设定的公平原则

例如,当有线程执行 tryLock() 方法的时候,一旦有线程释放了锁,那么这个正在 tryLock 的线程就能获取到锁,即使设置的是公平锁模式,即使在它之前已经有其他正在等待队列中等待的线程,简单地说就是 tryLock 可以插队

看源码就会发现

public boolean tryLock() {
    return sync.nonfairTryAcquire(1);
}

这里调用的就是 nonfairTryAcquire(),表明了是不公平的,和锁本身是否是公平锁无关

公平锁就是会按照多个线程申请锁的顺序来获取锁,从而实现公平的特性。非公平锁加锁时不考虑排队等待情况,直接尝试获取锁,所以存在后申请却先获得锁的情况,但由此也提高了整体的效率

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

公平锁和非公平锁介绍,为什么要“非公平”? 的相关文章

  • 互斥量、条件变量与pthread_cond_wait()函数的使用,详解(二)

    1 Linux 线程 进程与线程之间是有区别的 xff0c 不过Linux内核只提供了轻量进程的支持 xff0c 未实现线程模型 Linux是一种 多进程单线程 的操作系统 Linux本身只有进程的概念 xff0c 而其所谓的 线程 本质上
  • 网易视频云:流媒体服务器原理和架构解析

    网易视频云 是网易公司旗下的视频云服务产品 xff0c 以Paas服务模式 xff0c 向开发者提供音视频编解码SDK和开放API xff0c 助力APP接入音视频功能 今天 xff0c 网易视频云的技术专家给大家分享一篇流媒体技术性文章
  • MATLAB语言中int函数

    在MATLAB语言中 xff0c 求符号函数的定积分是使用int函数 xff0c 其调用格式如下 xff1a int F x a b a表示定积分的下限 xff1b b表示定积分的上限 xff1b 上式表示 xff0c 被积函数F在区间 a
  • matlab中的subs函数用法

    matlab中subs 是符号计算函数 xff0c 表示将符号表达式中的某些符号变量替换为指定的新的变量 xff0c 常用调用方式为 xff1a subs S OLD NEW 表示将符号表达式S中的符号变量OLD替换为新的值NEW 下面具体
  • Android配置临时ipv6地址

    Google公网DNS 2001 4860 4860 64642001 4860 4860 64 ifconfig wlan0 inet6 add IPV6ADDR ifconfig wlan0 inet6 add 2001 4860 48
  • MFC:pic控件的矩形的left、right、top、bottom 坐标位置

    CRect rect 然后 获取矩形控件 那么这个矩形控件的左上 和右下 分别对应 xff0c left xff0c top xff1b right xff0c bottom left xff0c top为左上角的点坐标 right xff
  • ubuntu下对sd卡 分区和格式化 挂载sd卡

    一 sd卡分区和格式化 1 查看自己的设备号 命令 xff1a mount 可以看到 最后一行即为sd卡的挂载目录 2 umount 由于sd卡插上之后会自动mount xff0c 所以需要unmout 命令 xff1a umount 路径
  • linux c 线程间同步(通信)的几种方法--互斥锁,条件变量,信号量,读写锁

    Linux下提供了多种方式来处理线程同步 xff0c 最常用的是互斥锁 条件变量 信号量和读写锁 下面是思维导图 xff1a 一 互斥锁 xff08 mutex xff09 锁机制是同一时刻只允许一个线程执行一个关键部分的代码 1 初始化锁
  • IMX头部详细解析之一 头部组成

    镜像组成 完整的imx镜像由以下四部分组成 xff1a Image Vector Table xff08 映像向量表 xff09 Boot Data xff08 启动数据 xff09 Device Configuration Data xf
  • IMX头部详细解析之二 头部生成工具

    前言 在之前的文章中 xff0c 介绍了imx的头部组成部分 xff0c 本文将介绍u boot如何通过mkimage工具构建imx的头部 正文 在imx6平台上进行裸机程序开发时 xff0c 通常需要添加imx头部信息 xff0c 才能使
  • Linux命令查询工具 O-LinuxCmd

    Linux命令查询工具 O linuxCmd 前言 一直以来 xff0c 遇到不熟悉的Linux命令都会直接百度 xff0c 找到一些命令查询网站再进行查询 xff0c 比如这个man linuxde net网站就很不错 虽然加入收藏夹就能
  • 嵌入式Linux利用ppp实现4G模块联网

    之前做项目时需要用到SIM7100模块 xff0c 便快速了解下ppp拨号 xff0c 实现了功能 xff0c 但是功能虽然实现了 xff0c 却依然有许多疑问 xff0c 这段时间有点时间 xff0c 打算更加详细的研究下 编译ppp2
  • O-ComTool V2.0.0串口调试工具

    O ComTool V2 1 0更新 xff0c 点击访问 O ComTool V2 0 0 简介 本次更新带来了 船新 的串口助手 xff0c 相较于V1 0 0版本 xff0c 代码重构 xff0c 添加了更多实用功能 xff0c 如
  • Marvell交换芯片88E6321/88E6320驱动总结-硬件篇

    芯片特性 Marvell 88E6321 88E6320 是一个7 Port千兆以太网交换芯片 支持最新的IEEEE802 1 Audio Video Bridging标准 芯片包含两个10 100 1000三速以太网收发器 xff08 P
  • Marvell交换芯片88E6321/88E6320驱动总结-寄存器篇

    由于我在项目中将该芯片作为PHY和SERDES使用 xff0c 因此本文内容主要还是围绕PHY和SERDES的相关功能 xff0c 至于其他功能则没有进行深入研究 工作模式 在之前的硬件篇中有提到 xff0c 该芯片有两种寻址模式 xff1
  • 更新 O-ComTool V2.1.0 串口调试助手

    FBI再次WARNING 测试时间较短 xff0c 有问题留言反馈哟 xff01 本次更新如下 实现更加人性化的暂停显示 上一版本中 xff0c 点击暂停显示时间过久 xff0c 就会出现卡顿的现象 xff0c 现在舍弃原来的方法 xff0
  • 什么是PN结

    FBI WARNING xff1a 本文是个人对PN结的理解 xff0c 若有错误 xff0c 望不吝赐教 xff0c 谢谢 xff01 二极管 三极管作为电路中的常见元件 xff0c 了解其工作原理是非常必要的 xff0c 但是在此之前
  • struct termios结构体详解

    一 数据成员 termios 函数族提供了一个常规的终端接口 xff0c 用于控制非同步通信端口 这个结构包含了至少下列成员 xff1a tcflag t c iflag 输入模式 tcflag t c oflag 输出模式 tcflag
  • PISSTV 树莓派慢扫描电视

    连接硬件 硬件 xff1a 树莓派 有驱动的摄像头 调试时需要usb wifi 配置树莓派 配置树莓派时要开启树莓派摄像头的支持 因为需要安装软件 xff0c 将树莓派连接到外网 测试摄像头拍照 使用raspistill命令进行拍照 ras
  • PID控制参数整定(调节方法)原理+图示+MATLAB调试

    序 首先最重要的是了解每个参数调节了系统响应的那些属性 xff0c 通过观察响应从而调节参数改变属性 PID的作用概述 xff1a 1 P产生响应速度和力度 xff0c 过小响应慢 xff0c 过大会产生振荡 xff0c 是I和D的基础 2

随机推荐

  • 关于VSCODE的插件 一

    官方API文档 1 要学好TypeScript 官方教程 1 1TypeScript是一门弱类型语言 强类型和弱类型主要是站在变量类型处理的角度进行分类的 这些概念未经过严格定义 xff0c 它们并不是属于语言本身固有的属性 xff0c 而
  • Pixhawk学习1——CMakeList.txt的解析

    在PX4的工程文件中 xff0c src modules下是具体的飞控代码 里面主要包含了传感器采集 姿态结算 姿态控制 xff0c 位置结算 位置控制等程序模块 在进行二次开发时 xff0c 需要添加的模块也是在这个文件夹里 每个文件夹里
  • Pixhawk学习2——uORB微对象请求代理及规则

    在Pixhawk中 xff0c 所有的功能被独立以进程模块为单位进行实现并工作 而每个进程模块都有一个 xff08 或多个 xff1f xff09 主题信息topic xff08 topic可以在Firmware msg里查看到所有的可使用
  • Pixhawk学习4——Commander相关分析

    Commander文件夹中的内容的作用主要为Pixhawk飞行模式的切换 该段程序会根据遥控器上的开关状态以及飞机飞行状态和各传感器性能状态进行判断 xff0c 最终实现飞行模式的切换 飞行模式切换主要涉及到以下几个文件 xff1a src
  • Pixhawk学习7——位置解算

    Pixhawk的位置解算分为两部分 xff0c 第一部分主要为传感器的数据获取 xff0c 而该部分最主要的就是GPS数据的提取 第二部分为与惯性器件之间的组合导航 组合导航的好处我就不用多说了 Pixhawk代码中目前主要有两处组合导航的
  • Pixhawk学习9——固定翼位置控制(L1控制+TECS总能量控制)

    本篇博客本来没有在之前的计划中 但由于最近项目上遇到了固定翼轨迹控制的一些问题 xff0c 所以就结合pix的程序学习总结了一下 不同于旋翼 xff0c 固定翼要实现位置变化必须得有一个轨迹变化过程 xff0c 因为它不像旋翼那样可以直接调
  • Pixhawk学习10.2——多旋翼位置控制

    10 1中介绍了目标位置点的计算逻辑 xff0c 知道下一时刻的目标位置后 xff0c 飞控需要根据当前位置进行计算 xff0c 依次得到期望速度 xff0c 期望拉力矢量 xff0c 期望姿态 至此就完成了多旋翼的位置控制 1 期望速度计
  • Http权威指南笔记(三)——HTTP报文

    前面介绍了URL是用于定位服务器上的资源 但是定位到资源后 xff0c 通过什么样的方式 规定来让客户端和服务端进行交流呢 xff1f 这就是本篇要介绍的HTTP报文 1 报文流 HTTP 报文是在 HTTP 应用程序之间发送的数据块 这些
  • 卡尔曼滤波算法详细推导

    一 预备知识 1 协方差矩阵 是一个维列向量 xff0c 是的期望 xff0c 协方差矩阵为 可以看出 协方差矩阵都是对称矩阵且是半正定的 协方差矩阵的迹是的均方误差 2 用到的两个矩阵微分公式 公式一 xff1a 公式二 xff1a 若是
  • 超声波测距实验

    超声波测距实验 超声波发射器向某一方向发射超声波 xff0c 在发射的同时开始计时 xff0c 超声波在空气中传播 xff0c 途中碰到障碍物就立即返回来 xff0c 超声波接收器收到反射波就立即停止计时 声波在空气中的传播速度为340m
  • Win7+Ubuntu双系统安装教程

    一 安装Win7 xff08 采用WinPE 43 gho xff09 1 设置笔记本电脑的BIOS xff0c 因为是安装win7 xff0c 最好采用Legacy模式 xff0c UEFI模式和win8 win10等以后的操作系统适配的
  • C语言——switch....case函数用法

    switch case函数用法 include lt stdio h gt int main int data char cdata printf 34 请输入一个数字 n 34 scanf 34 d 34 amp data switch
  • 计算机组成原理4(程序查询方式、程序中断方式、DMA方式及其I/O接口电路)

    文章目录 一 程序查询方式二 程序中断方式三 DMA方式 一 程序查询方式 1 程序查询方式的接口电路 2 符号说明 amp 与非门B工作触发器D完成触发器 3 程序查询工作过程 xff08 输入 xff09 xff08 1 xff09 当
  • FreeRTOS队列创建、发送和接收(备忘)

    目录 一 简介 1 1 开发环境 1 2 功能说明 二 动态创建队列 2 1 头文件声明 2 2 工程文件定义 2 3 创建队列 三 静态创建队列 3 1 头文件声明 3 2 工程文件定义 3 3 创建队列 四 写入消息 4 1 定义缓存变
  • 自动化面试题2

    一 画出 集电极开路 电压输出 互补输出 线性驱动输出 原理图 二 二进制 八进制 十进制以及十六进制之间的转化 三 PLC是什么 xff0c 并简述其优点和缺点 可编程控制器 xff08 Programmable Logic Contro
  • 【教程】win10 固态硬盘卡机卡死卡顿的真正原因!

    本人自从换了win10以后从来没卡过的电脑反正就是频繁的卡顿 xff0c 卡死 我试过以下方法 xff0c 有人说是微软拼音输入法的问题 xff0c 我直接更换了输入法 xff0c 这个效果是有 xff0c 卡机的频率降低了 xff0c 但
  • SizeChanged事件

    SizeChanged事件有的人不成功 xff0c 我也不知道什么原因不成功 xff0c 贴一下我成功的样子 xff01 xff01 xff01 Designer cs文件Form最下面放这个 this SizeChanged 43 61
  • centos7 安装docker

    sudo yum config manager add repo http mirrors aliyun com docker ce linux centos docker ce repo 出现以下内容则表示docker仓库配置成功 xff
  • 项目管理之启动:识别项目中的四类干系人

    干系人分析 指对项目干系人进行分析和归类 xff0c 有针对性地规划管理其核心诉求和期望 xff0c 让干系人可以更好地参与项目 xff0c 对项目产生积极影响 xff0c 从而更好地保障项目目标的成功达成 干系人分析的目的是什么呢 xff
  • 公平锁和非公平锁介绍,为什么要“非公平”?

    什么是公平和非公平 公平锁指的是按照线程请求的顺序 xff0c 来分配锁 xff1b 而非公平锁指的是不完全按照请求的顺序 xff0c 在一定情况下 xff0c 可以允许插队 但需要注意这里的非公平并不是指完全的随机 xff0c 不是说线程