为什么要设计非公平锁?

news2024/10/5 14:32:04

背景

公平:排队

非公平:在合适时机插队

非公平还是 ReentrantLock 的默认策略,排队时间不浪费了?

场景

来看这种场景

假如A持有一把锁,B请求这把锁,这时候B被挂起进入阻塞,A释放锁的时候,C来了进行请求,A就把锁给了C,因为唤醒B是需要很大开销的,很可能在B唤醒之前C就已经拿到这把锁执行完任务释放了这把锁,那就是双赢,C的执行速度相比于B被唤醒是很快的,这样设计就提高了整体运行效率

那假如公平呢?

那就进入等待队列等待,依次获得锁

不公平呢?

T1释放锁时,T5没排队直接请求,非公平策略:从整体效率考虑,这把锁会给T5

实验

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

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();
        }
    }
}

false:不公平

这里只给出非公平锁结果

Thread 0: Going to print a job
Thread 0: PrintQueue: Printing a Job during 8 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 9 seconds
Thread 0: The document has been printed
Thread 1: PrintQueue: Printing a Job during 8 seconds
Thread 1: PrintQueue: Printing a Job during 2 seconds
Thread 1: The document has been printed
Thread 2: PrintQueue: Printing a Job during 7 seconds
Thread 2: PrintQueue: Printing a Job during 8 seconds
...

本应是1获得锁但此时被0插队,由此可见0释放锁又获得了锁

优缺点

公平锁、非公平锁源码分析

public class ReentrantLock implements Lock, java.io.Serializable {
    private final Sync sync;
    abstract static class Sync extends AbstractQueuedSynchronizer {...}
    static final class FairSync extends Sync {...}
    static final class NonfairSync extends Sync{...}
}

公平锁和非公平锁加锁方法源码

公平锁

protected final boolean tryAcquire(int acquires) {
    final Thread current = Thread.currentThread();
    int c = getState();
    if (c == 0) {
        if (!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)) {
            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,等待队列中是否有线程在排队,公平锁:一旦有线程在排队,当前线程就不再尝试获取锁,对于非公平锁:无论有没有都尝试获取一下锁,获取不到再去排队

特例:tryLock方法

上源码

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

意思就是一旦有线程释放锁,那么正在tryLock的线程就能获取到锁,即便设置的是公平锁模式,即便他前面有等待的线程,它也可以插队

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/183179.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

点与线段的关系

点与线段的关系 对于向量a(x1,y1)和b(x2,y2) 点乘的数学意义&#xff1a;a * b x1x2 y1y2 点乘的几何意义&#xff1a;a * b |a||b|cosQ 这个可以看成是投影关系表达式&#xff1a;cosQ a * b / ( |a||b|) 令r cosQ&#xff1b; 求p点和线段AB的位置关系&#xff0c;可以…

将字符串根据指定的分隔符拆分为元组str.partition()

【小白从小学Python、C、Java】 【计算机等级考试500强双证书】 【Python-数据分析】 将字符串根据指定的分隔符拆分为元组 str.partition() 选择题 对于以下python代码最后输出的结果是? string "I Love Python" print("【显示】string.partition(Love)"…

Unity3d 微信小程序(小游戏)项目实现流量主接入功能(含源码)

前言 很早之前编写了Unity导出微信小游戏的博客&#xff0c;也尝试自己做了个Demo上线了&#xff0c;基本没更新过&#xff0c;不过几个月的时间&#xff0c;用户超过了一千&#xff0c;可以开通流量主了&#xff0c;大概率是因为上篇的帖子浏览量大了&#xff0c;扫码体验的人…

Aurora、Chip2chip、Ethernet(二)

摘要&#xff1a;Aurora、Chip2chip、Ethernet共用一个gt时钟的正确的解决方案以及在实际实现以及在实现过程中遇到的其它的问题。 我在实际中遇到的困难如下&#xff1a; 现在需要将三个ip共用一对GT时钟&#xff0c;一个Ethernet IP&#xff0c;一个Ethernet IP&#xff08…

每日学术速递1.29

CV - 计算机视觉 | ML - 机器学习 | RL - 强化学习 | NLP 自然语言处理 Subjects: cs.CV 1. Compact Transformer Tracker with Correlative Masked Modeling 标题&#xff1a;带有相关掩码建模的紧凑型变压器跟踪器 作者&#xff1a; Zikai Song, Run Luo, Junqing Yu, Y…

GLM国产大模型训练加速:性能最高提升3倍,显存节省1/3,低成本上手

作者&#xff5c;BBuf、谢子鹏、冯文 2017 年&#xff0c;Google 提出了 Transformer 架构&#xff0c;随后 BERT 、GPT、T5等预训练模型不断涌现&#xff0c;并在各项任务中都不断刷新 SOTA 纪录。去年&#xff0c;清华提出了 GLM 模型&#xff08;https://github.com/THUDM…

一句话说明线程和进程

知识点&#xff1a; 1、一句话说明线程和进程 2、操作系统为什么需要进程 3、为什么要引入线程 4、一图说明线程和进程的关系 一、一句话说明线程和进程 进程&#xff1a;是指⼀个内存中运⾏的应⽤程序&#xff0c;比如QQ、微信、浏览器等&#xff1b;⼀个应⽤程序可以同时运⾏…

CAS 和 Synchronized优化过程以及常见的锁策略

目录 &#x1f411;今日良言:追星赶月莫停留,平芜尽处是春山 &#x1f402;一、锁策略 &#x1f43c;二、CAS &#x1f42d;三、Synchronized &#x1f411;今日良言:追星赶月莫停留,平芜尽处是春山 &#x1f402;一、锁策略 锁策略是实现锁的时候,考虑出现锁竞争了该怎么…

电驱系统电磁兼容基础知识及测试方法

电驱系统电磁兼容基础知识及测试方法 学习参考&#xff1a;驱动视界公众号、百度百科、《电动汽车电机驱动系统EMC研究综述》 1.背景 2.电磁干扰三要素 3.电波暗室与屏蔽室的原理 4.测试方法 5.如何看测试数据 6.工作中需要注意的EMC的几点问题 7.案例 1.背景 汽车工业发展…

docker安装db2

第一步&#xff1a;下载镜像 docker pull ibmcom/db2express-c:latest备注&#xff1a;docker images -a 可以查看已安装镜像&#xff1b; 第二步&#xff1a;启动镜像 docker run -d --name db2 -p 50000:50000 -e DB2INST1_PASSWORD[数据库密码] -e LICENSEaccept ibmcom…

玩转PPT 第1节 PPT制作理念学习笔记

ppt神器islide 第1节 初步接触强大的工具1 PPT大神的课程总结1.1 骨架篇1.2 色彩篇1.3 对齐篇1.4 对比篇1.5 修饰篇1.6 字体篇1.7 素材篇1.8 线条篇1.8.1 可以随意画线条&#xff0c;填充空白1.8.2 在字体上画线条&#xff0c;做成艺术字1.8.3 做对称线条&#xff0c;比如递进三…

Bluesky勒索软件深度技术分析

0 1、 背景介绍 勒索软件作为一种流行的木马&#xff0c;近年来已成为最为常见的安全威胁之一。与其他威胁不同&#xff0c;勒索软件先向受害者表明自己的身份&#xff0c;再通过加密的方式使用户数据资产或计算资源无法正常使用&#xff0c;而恢复数据资产的唯一方法通常是支…

收藏破万,谷歌联手哈佛发布首个炼丹指南:教你科学化「调参」

调参不能只靠直觉&#xff0c;也是一门大学问&#xff01; 虽然算法工程师往往调侃自己是「调参侠」&#xff0c;但调参这件事可能真没想象中那么简单。 比如&#xff0c;你是不是经常会有疑惑到底该选择哪个优化器&#xff1f;一个batch放多少数据&#xff1f;超参数如何设置…

人工智能英文缩写怎么读,人工智能英文缩写大全

1、人工智能英文缩写是什么&#xff1f; AI。 人工智能&#xff0c;英文缩写为AI。它是研究、开发用于模拟、延伸和扩展人的智能的理论、方法、技术以及应用系统的一门技术科学。“十三五”以来&#xff0c;我国高度重视人工智能的发展&#xff0c;国内科研机构也围绕人工智能…

【Pytorch项目实战】之机器翻译:编码器-解码器、注意力机制AM

文章目录机器翻译 - 中英文翻译算法一&#xff1a;编码器-解码器&#xff08;Encoder - Decoder&#xff09;算法二&#xff1a;注意力机制&#xff08;Attention Model&#xff0c;AM&#xff09;2.1为何要引入注意力机制&#xff1f;2.2注意力机制的语义向量表示C计算2.3每个…

2023年首更,警惕6本SCISSCI期刊被剔除

2023年1月17日&#xff0c;Web of Science核心期刊目录首次更新。此次SCIE & SSCI期刊目录更新&#xff0c;与上次更新&#xff08;2022年12月&#xff09;相比&#xff0c;共有6本期刊被剔除出SCIE & SSCI期刊目录&#xff0c;详情如下&#xff1a; 公众号“Unionpub…

Redis实战9-全局唯一ID

发布优惠券的时候&#xff0c;每个店铺都可以发布优惠券&#xff0c;当用户抢购的时候,优惠券表中的id如果使用数据库的自增长ID会存在以下问题&#xff1a; 1&#xff1a;id的规律太明显&#xff0c;容易被刷 2&#xff1a;当数据量很大的时候&#xff0c;会受到单表数据的限…

三、分布式id,lua脚本,分布式锁,消息队列

文章目录优惠卷秒杀1.redis实现分布式ID2.优惠券秒杀下单3.超卖问题4.lua脚本5.分布式锁6.redis stream消息队列实现异步秒杀7.redis消息队列list实现消息队列PubSub实现消息队列stream实现消息队列stream的消息队列-消费者组学习黑马点评项目整理总结:https://www.bilibili.co…

5 个用于自动化的杀手级 Python 脚本

Python 是一种功能强大的语言&#xff0c;广泛用于自动执行各种任务。无论您是开发人员、系统管理员&#xff0c;还是只是想通过自动化日常任务来节省时间的人&#xff0c;Python 都能满足您的需求。 这里有 5 个 Python 脚本&#xff0c;可以帮助您自动执行各种任务 文章目录…

Spring Boot之Swagger

文章目录零 项目源码一 Swagger简介二 Spring Boot集成Swagger2.1 环境准备2.2 配置Swagger2.3 配置文档信息2.4 配置扫描接口2.5 配置开关Swagger2.6 配置API分组2.7 配置实体类2.8 常用注解零 项目源码 Swagger源码免费下载 一 Swagger简介 Swagger官网swagger是一款可以根…