Java中的公平锁和非公平锁

news2024/9/25 17:18:52

1、什么是公平锁和非公平锁

公平锁和非公平锁是指在多线程环境下,如何对锁进行获取的顺序和策略的不同。

公平锁是指多个线程按照申请锁的顺序来获取锁,即先到先得的策略。当一个线程释放锁之后,等待时间最长的线程将获得锁。公平锁的优点是保证了每个线程的公平性,不存在饥饿现象,但是由于需要维护一个等待队列,因此会增加系统的开销。

非公平锁是指多个线程获取锁的顺序是不确定的,不一定按照申请锁的顺序来获取锁。当一个线程释放锁之后,锁的获取是由系统的调度算法来决定的。非公平锁的优点是可以减少线程上下文切换的开销,提高系统的吞吐量,但是容易出现饥饿现象,即某些线程可能会一直获取不到锁。

一般来说,公平锁适用于对线程公平性要求比较高的场景,而非公平锁适用于对性能要求比较高的场景。但是在具体应用时,需要根据实际情况来选择合适的锁。

● 公平锁:是指多个线程按照申请的顺序来获取值。在并发环境中,每一个线程在获取锁时会先查看此锁维护的等待队列,如果为空,或者当前线程是等待队列的第一个就占有锁,否者就会加入到等待队列中,以后会按照 FIFO 的规则获取锁

● 非公平锁:是指多个线程获取值的顺序并不是按照申请锁的顺序,有可能后申请的线程比先申请的线程优先获取锁。在并发环境中一上来就尝试占有锁,如果失败再进行排队,可能会造成优先级翻转或者饥饿现象

    // 常用的ReentrantLock无参构造默认是非公平锁

    /**
     * Creates an instance of {@code ReentrantLock}.
     * This is equivalent to using {@code ReentrantLock(false)}.
     */
    public ReentrantLock() {
        sync = new NonfairSync();
    }

    /**
     * Creates an instance of {@code ReentrantLock} with the
     * given fairness policy.
     *
     * @param fair {@code true} if this lock should use a fair ordering policy
     */
    public ReentrantLock(boolean fair) {
        sync = fair ? new FairSync() : new NonfairSync();
    }

2、Java中的公平锁和非公平锁

Java中的公平锁和非公平锁主要有以下几种:

ReentrantLock的公平锁和非公平锁:ReentrantLock是Java中常用的锁实现类之一,它提供了公平锁和非公平锁两种模式。在创建ReentrantLock对象时,可以通过构造函数传入一个布尔类型的fair参数来指定锁的模式。如果fair为true,则创建公平锁;如果fair为false,则创建非公平锁。

ReentrantReadWriteLock的公平锁和非公平锁:ReentrantReadWriteLock是一个读写锁,它也提供了公平锁和非公平锁两种模式。在创建ReentrantReadWriteLock对象时,可以通过构造函数传入一个布尔类型的fair参数来指定锁的模式。如果fair为true,则创建公平锁;如果fair为false,则创建非公平锁。

StampedLock的乐观锁和悲观锁:StampedLock是Java 8中新增的一种锁实现类,它提供了乐观锁和悲观锁两种模式。在使用StampedLock时,可以通过调用tryOptimisticRead()方法来获取乐观锁,或者通过调用readLock()方法来获取悲观锁。乐观锁是一种无锁的机制,它不会阻塞线程,但是需要通过validate()方法来检查锁是否仍然有效。

Synchronized的非公平锁:Synchronized是Java中内置的锁机制,它默认采用非公平锁模式。在使用Synchronized时,如果多个线程同时请求锁,则会根据系统的调度算法来决定哪个线程获取锁。

公平锁和非公平锁的性能和效率都会受到多种因素的影响,如锁的争用情况、线程的数量、系统的负载等。在实际应用中,需要根据具体情况选择合适的锁模式。

3、为什么Synchronized是非公平锁

Synchronized是Java中内置的锁机制,它的锁模式是非公平锁,这是因为Synchronized的实现方式是基于对象监视器(monitor)的。

在Java中,每个对象都有一个与之关联的monitor,当一个线程需要获取某个对象的锁时,它会首先尝试获取这个对象关联的monitor。如果monitor已经被其他线程占用,那么这个线程就会进入monitor的等待队列中,等待其他线程释放锁。

在Synchronized中,当一个线程释放锁时,JVM会从等待队列中随机选择一个线程来获取锁,而不是按照申请锁的顺序来获取锁,因此Synchronized是一种非公平锁。这种实现方式的优点是可以减少线程上下文切换的开销,提高系统的吞吐量,但是容易出现饥饿现象,即某些线程可能会一直获取不到锁。

Synchronized也可以通过在代码中使用wait()和notify()方法来实现公平锁,但是这种方式比较复杂,容易出错,而且性能也不如ReentrantLock的公平锁实现方式。因此,在实际应用中,如果需要公平锁,建议使用ReentrantLock。

4、Synchronized代码示例

下面是一个简单的Synchronized使用示例:

4.1、修饰方式

public class SynchronizedExample {
    private int count = 0;
 
    public synchronized void increment() {
        count++;
    }
    public static void main(String[] args) throws InterruptedException {
        SynchronizedExample example = new SynchronizedExample();
        Thread thread1 = new Thread(() -> {
            for (int i = 0; i < 10000; i++) {
                example.increment();
            }
        });
 
        Thread thread2 = new Thread(() -> {
            for (int i = 0; i < 10000; i++) {
                example.increment();
            }
        });
 
        thread1.start();
        thread2.start();
 
        thread1.join();
        thread2.join();
 
        System.out.println("Count: " + example.count);
    }
}

输入结果如下:

在这个示例中,Synchronized被用于修饰increment()方法,这样在同一时刻只有一个线程可以执行该方法。这个示例中创建了两个线程,分别对count变量进行自增操作。由于Synchronized的作用,这些操作是互斥的,所以最终输出的count值应该是20000。

4.2、修饰代码块

除了修饰方法,Synchronized还可以修饰代码块。下面是一个使用Synchronized修饰代码块的示例:

public class SynchronizedExample {
    private int count = 0;
    private final Object lock = new Object();
 
    public void increment() {
        synchronized (lock) {
            count++;
        }
    }
 
    public static void main(String[] args) throws InterruptedException {
        SynchronizedExample example = new SynchronizedExample();
        Thread thread1 = new Thread(() -> {
            for (int i = 0; i < 10000; i++) {
                example.increment();
            }
        });
 
        Thread thread2 = new Thread(() -> {
            for (int i = 0; i < 10000; i++) {
                example.increment();
            }
        });
 
        thread1.start();
        thread2.start();
 
        thread1.join();
        thread2.join();
 
        System.out.println("Count: " + example.count);
    }
}

在这个示例中,Synchronized被用于修饰代码块,这样在同一时刻只有一个线程可以执行该代码块。在这个示例中,lock对象被用于作为Synchronized锁的对象。

5、总结

需要注意的是,Synchronized锁的是对象,而不是代码。在同一个对象上使用Synchronized修饰的代码块或方法是互斥的,但不同对象上的Synchronized代码块或方法并不互斥。

Synchronized虽然可以保证线程安全,但是它会导致性能问题。在使用Synchronized时需要注意以下几点:

尽量缩小Synchronized的作用范围,只在必要的代码块或方法上使用Synchronized。

尽量不要在Synchronized代码块或方法中调用其他耗时的方法,这会导致其他线程长时间等待。

尽量使用Lock接口代替Synchronized,因为Lock接口提供了更灵活的锁定机制。

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

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

相关文章

第2章 信息技术知识

第2章 信息技术知识 本章简要叙述了信息技术相关基础知识&#xff0c;包含软件工程、面向对象系统分析与设计、应用集成技术、计算机网络技术和新一代信息技术内容。 2.1 软件工程 随着所开发软件的规模越来越大、复杂度越来越高&#xff0c;加之用户需求又并不十分明确&…

【RIP实验-熟悉基础配置】

实验拓扑 实验要求 根据实验拓扑的IP地址分配&#xff0c;为所有设备配置对应的IP地址和环回地址。全网运行RIPv2&#xff0c;将R1、R2、R3和R4的物理端口、Loopback地址和10.1.00网段进行宣告。并在rip协议下配置路由自动汇总&#xff0c;观察R1/R2是否能够收到10.0.0.0的详细…

【Pytorch实用教程】transformer中创建嵌入层的模块nn.Embedding的用法

文章目录 1. nn.Embedding的简单介绍1.1 基本用法1.2 示例代码1.3 注意事项2. 通俗的理解num_embeddings和embedding_dim2.1 num_embeddings2.2 embedding_dim2.3 使用场景举例结合示例1. nn.Embedding的简单介绍 nn.Embedding 是 PyTorch 中的一个模块,用于创建一个嵌入层。…

MATLAB engine for python调用m文件函数输出变量值python调用MATLAB函数混合编程

MATLAB engine for python调用m文件函数输出变量值python调用MATLAB函数混合编程 说明(废话)解决方案总结 说明(废话) python调用MATLAB函数&#xff0c;MATLAB函数实现在m文件&#xff0c;python直接调用MATLAB中的函数。 首先还是要安装好MATLAB engine python setup.py ins…

3d已经做好的模型怎么改单位?---模大狮模型网

在展览3D模型设计行业中&#xff0c;经常会遇到需要将已完成的模型进行单位转换的需求。这可能涉及从一种度量单位转换为另一种&#xff0c;例如从英制单位转换为公制单位&#xff0c;或者根据特定的展览场地要求进行尺寸调整。本文将探讨如何有效地修改已完成的3D模型的单位&a…

标签印刷检测,如何做到百分百准确?

印刷标签是一种用于标识、识别或包装产品的平面印刷制品。这些标签通常在纸张、塑料膜、金属箔等材料上印刷产品信息、条形码、图像或公司标识&#xff0c;以便于产品识别和管理。印刷标签有各种形状、尺寸和材质&#xff0c;可以根据具体需求进行定制设计。常见的印刷标签包括…

分类模型的算法性能评价

一、概述 分类模型是机器学习中一种最常见的问题模型&#xff0c;在许多问题场景中有着广泛的运用&#xff0c;是模式识别问题中一种主要的实现手段。分类问题概况起来就是&#xff0c;对一堆高度抽象了的样本&#xff0c;由经验标定了每个样本所属的实际类别&#xff0c;由特定…

南京邮电大学运筹学课程实验报告1 线性规划求解 指导

一、题目描述 实验 一 线性规划求解 实验属性&#xff1a; 验证性     实验目的 1&#xff0e;理解线性规划解的基本概念&#xff1b; 2&#xff0e;掌握运筹学软件的使用方法&#xff1b; 3. 掌握线性规划的求解原理和方法。 实验内容 认…

MQTT是什么,物联网

写文思路&#xff1a; 以下从几个方面介绍MQTT&#xff0c;包括&#xff1a;MQTT是什么&#xff0c;MQTT和webSocket的结合&#xff0c;以及使用场景&#xff0c; 一、MQTT是什么 MQTT&#xff08;Message Queuing Telemetry Transport&#xff09;是一种轻量级的发布/订阅消息…

手慢无,速看︱PMO大会内部学习资料

全国PMO专业人士年度盛会 每届PMO大会&#xff0c;组委会都把所有演讲嘉宾的PPT印刷在了会刊里面&#xff0c;供大家会后回顾与深入学习。 第十三届中国PMO大会-会刊 《2024第十三届中国PMO大会-会刊》 &#xff08;内含演讲PPT&#xff09; 会刊&#xff1a;750个页码&…

泽众云真机-远程自助兼容性测试报告新功能已上线

之前泽众云真机平台有用户咨询&#xff0c;是否支持团队管理&#xff0c;因项目时间上线紧急&#xff0c;需要多人参与测试&#xff0c; 否则项目有延期的风险&#xff0c;后来用户选择了泽众云测试平台的第三方专业兼容性测试服务。事后技术团队认真评估用户需要&#xff0c;从…

京东商品历史价格查询

当前资料来源于网络&#xff0c;禁止用于商用&#xff0c;仅限于学习。 下载京东APP 登录后 打开商品详情就可以看到 要获取京东商品的历史价格&#xff0c;你可以在京东网站上搜索该商品&#xff0c;并进入该商品的详情页面。然后&#xff0c;在页面中找到“商品详情”一栏&…

电脑32位和62位是什么意思

在现代计算机世界中&#xff0c;32位和64位是两个常见的术语&#xff0c;但许多用户可能不太清楚它们的确切含义以及它们之间的区别。本文将详细介绍32位和64位计算机的基本概念、如何查看您的计算机是32位还是64位&#xff0c;以及它们对用户的实际影响。 32位与64位的基本概…

针对tcp不出网打——HTTP封装隧道代理(以CFS演示)

目录 上传工具到攻击机 使用说明 生成后门文件 由于电脑短路无法拖动文件&#xff0c;我就wget发送到目标主机tunnel.php文件​ 成功上传​ 可以访问上传的文件 启动代理监听 成功带出 后台私信获取弹药库工具reGeorg 上传工具到攻击机 使用说明 生成后门文件 pyt…

【Linux】进程(9):进程控制3(进程程序替换)

大家好&#xff0c;我是苏貝&#xff0c;本篇博客带大家了解Linux进程&#xff08;9&#xff09;进程控制1&#xff0c;如果你觉得我写的还不错的话&#xff0c;可以给我一个赞&#x1f44d;吗&#xff0c;感谢❤️ 目录 &#xff08;A&#xff09;什么是进程程序替换&#xf…

PLC数采网关在实际应用中有哪些效能?天拓四方

在工业自动化领域中&#xff0c;PLC扮演着至关重要的角色&#xff0c;它负责控制和监测生产线的各个环节。然而&#xff0c;随着工业4.0的推进和智能制造的快速发展&#xff0c;单纯依靠PLC进行现场控制已无法满足企业对数据集中管理、远程监控和智能分析的需求。因此&#xff…

优化爬虫体验:揭秘IP重复率过高问题解决方案

在当今信息爆炸的时代&#xff0c;网络中蕴藏着大量宝贵的数据&#xff0c;而爬虫技术成为我们提取这些数据的重要工具。然而&#xff0c;随着爬虫的广泛使用&#xff0c;IP重复率高的问题也随之而来。本篇博文将揭秘解决这一问题的关键方法——使用IP代理。 一、 IP高重复问题…

钡铼网关: 轻松实现PLC与OPC UA服务器的双向通信

在当今工业4.0的大潮下&#xff0c;实现不同设备、系统之间的高效通信和数据交换已大势所趋&#xff01;PLC与OPC UA服务器的对接&#xff0c;对于打造智能工厂具有重要意义&#xff0c;本文将深入探讨钡铼技术的网关如何实现这一过程&#xff0c;为用户提供快速且低成本的解决…

lvs集群、NAT模式和DR模式

lvs集群概念 全称是linux virtual server&#xff0c;是在Linux的内核层面实现负载均衡的软件。 主要作用&#xff1a;将多个后端服务器组成一个高可用高性能的服务器集群&#xff0c;通过负载均衡的算法将客户端的请求分发到后端的服务器上&#xff0c;来实现高可用和负载均…

Python 爬虫与 Java 爬虫:相似之处、不同之处和选项

在信息时代&#xff0c;网络上可用的数据量巨大且不断增长。为了从这些数据中提取有用的信息&#xff0c;爬虫已成为一种重要的技术。Python 和 Java 都是流行的编程语言&#xff0c;都具有强大的爬虫功能。本文将深入探讨 Python 爬虫和 Java 爬虫之间的差异&#xff0c;以帮助…