Java并发三大利器之深度解析

推荐阅读

AI文本 OCR识别最佳实践

AI Gamma一键生成PPT工具直达链接

玩转cloud Studio 在线编码神器

玩转 GPU AI绘画、AI讲话、翻译,GPU点亮AI想象空间

资源分享

「java、python面试题」来自UC网盘app分享,打开手机app,额外获得1T空间
https://drive.uc.cn/s/2aeb6c2dcedd4
AIGC资料包
https://drive.uc.cn/s/6077fc42116d4
https://pan.xunlei.com/s/VN_qC7kwpKFgKLto4KgP4Do_A1?pwd=7kbv#
821日更新自媒体素材网站,方便你的视频剪辑
SDXL专区8个教程,SD六日更新6个教程
8月资料专题已更新
https://yv4kfv1n3j.feishu.cn/docx/MRyxdaqz8ow5RjxyL1ucrvOYnnH前置条件:https://cloud.tencent.com/developer/article/2304343 ←文章三连评论666

1. 前言

在Java开发中,多线程编程是一个常见而重要的话题。随着计算机硬件的发展,多核处理器的普及以及对性能的不断追求,充分利用多线程来实现并发执行成为了提高程序效率和性能的必要手段。然而,多线程编程中存在诸多问题,如线程安全和协调等,而Java提供了一些并发工具来解决这些问题。本文将深入探讨三大并发利器:Synchronized、ReentrantLock和CAS。

2. Synchronized实现原理

Synchronized是Java中最基本也是最常用的同步机制,它的实现原理涉及到Java的对象头和监视器锁。

2.1 对象头

每个Java对象都有一个对象头,用于存储对象的元信息。对象头中包含了Mark Word和Klass Pointer等字段。其中Mark Word用于存储对象的标记信息,如锁状态、GC标记等;Klass Pointer指向对象所属的类的元数据。

2.2 监视器锁

在Synchronized中,每个对象都有一个关联的监视器锁(也称为内部锁或互斥锁)。监视器锁是基于对象的,每个对象只有一个锁。当一个线程要执行被Synchronized修饰的代码块时,首先要获取该代码块关联对象的锁,如果锁被其他线程占用,则需要等待。

Synchronized的实现是通过对象头中的Mark Word来实现的。当一个线程获取到锁时,会将对象头中的Mark Word的标记位修改为锁定状态,其他线程在尝试获取锁时会发现该标记位已被锁定,于是进入等待队列。当持有锁的线程释放锁时,会将对象头中的Mark Word还原。

2.3 示例代码

下面是一个简单的示例代码,展示了Synchronized的用法:

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

在上述代码中,通过Synchronized关键字保证了count的原子性操作,避免了多线程访问的竞争问题。

3. ReentrantLock的实现原理(AQS)

ReentrantLock是Java中另一个常用的同步机制,与Synchronized相比,ReentrantLock提供了更丰富的功能,如可重入、公平性等。它的实现基于AQS(AbstractQueuedSynchronizer)。

3.1 AQS简介

AQS是Java中用于实现同步器的框架,是ReentrantLock、CountDownLatch等同步工具的基础。AQS使用一个FIFO队列来管理访问同步资源的线程。

AQS核心组件包括Sync Queue(同步队列)、Condition Queue(条件队列)、状态标记等。

3.2 ReentrantLock的实现

在ReentrantLock的内部,有一个Sync类,用于实现锁获取和释放等操作。Sync类有两个子类:NonfairSync和FairSync,分别用于实现非公平锁和公平锁。

ReentrantLock的实现原理可以概括为以下几个步骤:

  1. 非公平锁和公平锁的获取:根据锁的状态和线程是否已经持有锁来判断是否能够获取锁。在非公平锁中,获取锁的线程只需要判断锁的状态和自身是否已经持有锁即可;而在公平锁中,获取锁的线程还需要判断是否存在排在自己前面的等待线程。
  2. 锁释放:当一个线程释放锁时,需要将当前持有锁的线程设置为null,并通知等待队列中的下一个线程获取锁。
  3. 同步队列(Sync Queue)和条件队列(Condition Queue)的管理:AQS使用两个队列来管理线程的等待和唤醒。同步队列用于存储等待获取锁的线程,按照FIFO的顺序进行管理。条件队列用于通过Condition接口提供的await()和signal()等方法来实现线程的等待和唤醒。

3.3 示例代码

下面是一个使用ReentrantLock实现线程安全的计数器的示例代码:

import java.util.concurrent.locks.ReentrantLock;public class ReentrantLockDemo {private static int count = 0;private static final ReentrantLock lock = new ReentrantLock();public static void main(String[] args) throws InterruptedException {Thread t1 = new Thread(() -> {lock.lock();try {for (int i = 0; i < 100000; i++) {count++;}} finally {lock.unlock();}});Thread t2 = new Thread(() -> {lock.lock();try {for (int i = 0; i < 100000; i++) {count++;}} finally {lock.unlock();}});t1.start();t2.start();t1.join();t2.join();System.out.println("Count: " + count);}
}

在上述代码中,通过ReentrantLock关键字保证了count的原子性操作。通过lock()方法获取锁,并在finally块中使用unlock()方法释放锁,确保线程在任何情况下都能释放锁。

4. CAS的实现原理

CAS(Compare and Swap)是一种乐观锁机制,利用CPU的原子指令实现无锁并发。它的实现依赖于底层硬件的支持,并在Java中通过Unsafe类提供了相应的接口。

4.1 CAS操作步骤

CAS操作包含三个基本操作步骤:读取内存值、比较内存值与期望值、更新内存值。当期望值与内存值相同时,将新值写入内存;否则,不进行更新。

在Java中,CAS操作通常使用AtomicInteger、AtomicBoolean等原子类来实现。这些原子类内部使用了Unsafe类提供的CAS操作,保证了操作的原子性和线程安全性。

4.2 示例代码

下面是一个使用CAS实现线程安全的计数器的示例代码:

import java.util.concurrent.atomic.AtomicInteger;public class CASDemo {private static AtomicInteger count = new AtomicInteger(0);public static void main(String[] args) throws InterruptedException {Thread t1 = new Thread(() -> {for (int i = 0; i < 100000; i++) {count.incrementAndGet();}});Thread t2 = new Thread(() -> {for (int i = 0; i < 100000; i++) {count.incrementAndGet();}});t1.start();t2.start();t1.join();t2.join();System.out.println("Count: " + count.get());}
}

在上述代码中,使用AtomicInteger类来保证了count的原子性操作。通过incrementAndGet()方法实现自增操作,无需加锁即可保证线程安全。

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

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

相关文章

springMVC之视图

文章目录 前言一、ThymeleafView二、转发视图三、重定向视图四、视图控制器view-controller五、补充总结 前言 SpringMVC中的视图是View接口&#xff0c;视图的作用渲染数据&#xff0c;将模型Model中的数据展示给用户。 SpringMVC视图的种类很多&#xff0c;默认有转发视图和…

vscode远程调试

安装ssh 在vscode扩展插件搜索remote-ssh安装 如果连接失败&#xff0c;出现 Resolver error: Error: XHR failedscode 报错&#xff0c;可以看这篇帖子vscode ssh: Resolver error: Error: XHR failedscode错误_阿伟跑呀的博客-CSDN博客 添加好后点击左上角的加号&#xff0…

【Python机器学习】实验16 卷积、下采样、经典卷积网络

文章目录 卷积、下采样、经典卷积网络1. 对图像进行卷积处理2. 池化3. VGGNET4. 采用预训练的Resnet实现猫狗识别 TensorFlow2.2基本应用5. 使用深度学习进行手写数字识别 卷积、下采样、经典卷积网络 1. 对图像进行卷积处理 import cv2 path data\instance\p67.jpg input_…

微信小程序picker组件的简单使用 单选

<picker mode"selector" range"{{classData}}" bindchange"bindClassChange" value"{{classIndex}}" range-key"className"><view class"picker">{{classData[classIndex].className || 请选择班级}}…

OpenGL调试时输出显存帧到图片的一些方法

1. 从帧缓存读取像素 bool GLUtils::saveRender(const std::string& tag,int w, int h,const char* func_name, int line){std

Linux 线程同步——条件变量

一、条件变量的概念 如果说互斥锁是用于同步线程对共享数据的访问的话&#xff0c;那么条件变量则是用于在线程之间同步共享数据的值。条件变量提供了一种线程间的通知机制&#xff1a;当某个共享数据达到某个值的时候&#xff0c;唤醒等待这个共享数据的线程。如下图所示&…

vue3中使用第三方插件mitt实现任意组件通讯

vue3中使用第三方插件mitt实现任意组件通讯 组件通讯是vue3组合式开发的核心之一&#xff0c;现在我在写代码时&#xff0c;一个组件的代码超过了200行&#xff0c;基本都会拆分组件。组件拆分后&#xff0c;组件之间的通讯就很重要&#xff0c;总结了一下&#xff0c;目前有这…

【SQL应知应会】索引(三)• MySQL版:聚簇索引与非聚簇索引;查看索引与删除索引;索引方法

欢迎来到爱书不爱输的程序猿的博客, 本博客致力于知识分享&#xff0c;与更多的人进行学习交流 本文收录于SQL应知应会专栏,本专栏主要用于记录对于数据库的一些学习&#xff0c;有基础也有进阶&#xff0c;有MySQL也有Oracle 索引 • MySQL版 前言一、索引1.简介2.索引类型之逻…

【李沐】3.2线性回归从0开始实现

%matplotlib inline import random import torch from d2l import torch as d2l1、生成数据集&#xff1a; 看最后的效果&#xff0c;用正态分布弄了一些噪音 上面这个具体实现可以看书&#xff0c;又想了想还是上代码把&#xff1a; 按照上面生成噪声&#xff0c;其中最后那…

利用大模型反馈故障的解决方案

背景 观测云有两个错误巡检脚本&#xff0c;RUM 错误巡检和 APM 错误巡检&#xff0c;代码均开源。 错误巡检的主要目的是发现新出现的错误消息(error stack)&#xff0c;原有的巡检在上报了相应的事件报告后&#xff0c;只是定位了问题&#xff0c;并没有给出合适的解决方案。…

C++(3)C++对C的扩展Extension

类型增强 1、类型更加严格 不初始化&#xff0c;无法通过编译&#xff1b;C不初始化&#xff0c;则随机赋值 #include <iostream> #include <stdlib.h>int main() {const int a 100; //真正的const,无法修改 // int *p &a; 报错const int *p…

Pandas基础知识

文章目录 Pandas的数据结构Series --- 由数据和索引组成&#xff08;索引&#xff08;index&#xff09;在左&#xff0c;数据&#xff08;values&#xff09;在右&#xff09;DataFrame --- 索引包括行索引和列索引&#xff0c;每列数据可以是不同的类型 Pandas的索引操作 ---…

SpringMVC拦截器学习笔记

SpringMVC拦截器 拦截器知识 拦截器(Interceptor)用于对URL请求进行前置/后置过滤 Interceptor与Filter用途相似但实现方式不同 Interceptor底层就是基于Spring AOP面向切面编程实现 拦截器开发流程 Maven添加依赖包servlet-api <dependency><groupId>javax.se…

C++学习之九

1)普通类的成员函数模板 class A { public:template<typename T> //类的成员函数模板,//成员函数模板和函数模板长得样子一样&#xff01;void func(T tmp); };template<typename T> void A::func(T tmp) {cout << tmp << endl; }int main() {A a;a.…

nginx代理webSocket链接,webSocket频繁断开重连

一、场景 1、使用nginx代理webSocket链接&#xff0c;消息发送和接收都是正常的&#xff0c;但webSocket链接会频繁断开重连 2、如果不使用nginx代理则一切正常 3、程序没有做webSocket心跳处理 如下图 二、nginx代理配置 upstream cloud_ass {#ip_hash;server 192.168.1.…

2023年国赛数学建模思路 - 案例:随机森林

文章目录 1 什么是随机森林&#xff1f;2 随机深林构造流程3 随机森林的优缺点3.1 优点3.2 缺点 4 随机深林算法实现 建模资料 ## 0 赛题思路 &#xff08;赛题出来以后第一时间在CSDN分享&#xff09; https://blog.csdn.net/dc_sinor?typeblog 1 什么是随机森林&#xff…

leetcode做题笔记95. 不同的二叉搜索树 II

给你一个整数 n &#xff0c;请你生成并返回所有由 n 个节点组成且节点值从 1 到 n 互不相同的不同 二叉搜索树 。可以按 任意顺序 返回答案。 思路一&#xff1a;递归 struct TreeNode ** partition(int start, int end, int* returnSize){*returnSize 0;int size 32;stru…

从2023年世界机器人大会发现机器人新趋势

机器人零部件为何成2023年世界机器人大会关注热门&#xff1f; 在原先&#xff0c;机器人的三大核心零部件是控制系统中的控制器、驱动系统中的伺服电机和机械系统中的精密减速器。如今&#xff0c;机器人的主体框架结构已经落实&#xff0c;更多机器人已经开始深入到各类场景中…

c++ std::sort的简单用法

直接看代码即可&#xff0c;对于lambda部分的解释&#xff1a;a,b基本算作两个抽象的比较对象&#xff0c;每次会比较这两个&#xff0c;返回true:表示a应该排在b前面(a<b)&#xff0c;返回false:表示b应该排在a前面(a>b)&#xff0c;具体可查看cpprefernece #include &…

Prompt本质解密及Evaluation实战(一)

一、基于evaluation的prompt使用解析 基于大模型的应用评估与传统应用程序的评估不太一样&#xff0c;特别是基于GPT系列或者生成式语言模型&#xff0c;因为模型生成的内容与传统意义上所说的内容或者标签不太一样。 以下是借用了ChatGPT官方的evaluation指南提出的对结果的具…