【Java技术专题】「入门到精通系列教程」深入探索Java特性中并发编程体系的原理和实战开发指南( 线程基础技术专题)

news2024/9/27 23:22:56

深入探索Java特性中并发编程体系的原理和实战开发指南

  • 并发编程介绍
    • 什么是并发编程
      • 并发编程的好处是什么
      • 并发编程的挑战是什么
      • 并发编程模型有哪些
      • 如何学习并发编程
      • 本系列专题文章大全
  • 实战原理
    • 计算的问题
      • 简单的方法:更快的CPU来遍历
      • 靠谱的方法:分而治之来处理
      • 进一步的办法:Fork/Join技术
    • 线程是并发编程的基础
      • 线程
      • 技术选型
      • 内存中的可见部分
      • synchronized同步机制
        • 保证原子性和可见性
        • 锁的类型和范围
        • 线程的Java Monitors监视器
        • 线程的可见性
          • volatile关键字
          • 脆弱的volatile的使用条件:
          • 线程:独占锁
          • 线程:分拆锁
          • 线程:分离锁
  • 教父Joshua Bloch说线程
  • 书籍推荐

并发编程介绍

当今软件开发领域越来越强调性能和伸缩性,因此,利用并发编程可以更好地利用计算资源,提高应用程序的性能和响应速度。以下是一些关于并发编程的相关信息供您参考。

什么是并发编程

并发编程是指在一个程序中同时执行多个独立的计算任务,并通过各种手段来协调不同任务之间的交互,从而提高程序的效率和可扩展性。

并发编程的好处是什么

并发编程可以使程序可以同时利用多个CPU核心执行不同的任务,从而提升程序的效率和性能。此外,使用并发编程可以简化需要相互协调的任务之间的通信和同步,减少系统的复杂度和出错的风险。

并发编程的挑战是什么

并发编程面临许多挑战,如资源竞争、死锁、饥饿和活锁等问题。同时,在并发系统中,程序的错误也可能导致数据不一致和安全漏洞等问题。因此,在设计和开发并发系统时需要仔细考虑各种问题。

并发编程模型有哪些

常见的并发编程模型包括多线程模型、多进程模型和协程模型。每种模型都有自己的特点,相应的编程语言和框架也提供了支持。

如何学习并发编程

学习并发编程需要掌握并发编程的基本理论,同时需要熟悉各种并发编程模型和工具。建议初学者先学习基础的多线程编程和锁机制,逐步学习更高级的并发编程模型和相关技术,如Actor模型、RxJava、Go语言等。另外,实践也是学习并发编程的关键,可以通过实际编写并发程序来获得经验和技能。

本系列专题文章大全

在这里插入图片描述

实战原理

计算的问题

如何更快地计算一个包含亿级 Integer 类型数值的 List 的总和?
在这里插入图片描述

简单的方法:更快的CPU来遍历

单线程处理大数据量的数据集合的分析是一项挑战性的任务,因为单线程处理大数据量的数据集合可能会导致程序的运行速度变慢,甚至崩溃。伴随着数据量越来越大,耗费的时间约会越来越长,如下图所示。
在这里插入图片描述

靠谱的方法:分而治之来处理

在对性能的追求很可能是并发bug唯一最大的来源!同样不是免费的午餐,需要学习和批量实践。

在这里插入图片描述

进一步的办法:Fork/Join技术

Fork/Join是一种并行编程技术,常用于解决分治问题。具体来说,它将一个大问题分成若干个小问题,递归地将小问题分解成更小的子问题,直到问题的规模足够小可以被直接解决。然后将解决子问题的结果合并起来,得到大问题的解。Fork/Join使用了线程池的概念,并且自动运用一些启发式策略优化任务调度,从而保证任务的高效执行。Fork/Join 技术在并行计算中发挥着重要作用,能够提高多线程执行效率和程序处理大规模数据的能力。
在这里插入图片描述
在这个模式中,原始任务被递归地分解成更小的子任务,直到这些任务足够小,可以被直接处理。每个子任务都是在一个单独的线程中运行的,然后将它们的结果合并在一起,直到最终产生原始任务的结果。这种方式可以很好地利用多核CPU,从而提高性能。

线程是并发编程的基础

在Java中,线程技术是支持并发编程的基础。并发编程是指多个线程同时执行任务,它能够充分利用计算机的多核处理器,提高程序的执行效率和响应速度。

线程

线程:是实现多任务并发执行的关键。在Java中,我们可以使用多线程技术来同时执行多个任务,提高程序的并发性和吞吐量。因此,Java中的线程技术是并发编程的基础。
在这里插入图片描述

  • 多线程并发中:如果修改了共享变量的值,必须将其同步回主内存,其他线程才能访问到。

  • 为了保证内存访问的顺序,可以使用Java提供的同步机制或volatile关键字。

  • Cache coherency指管理多处理器系统的高速缓存区结构,确保数据在高速缓存区到内存的传输中不会丢失或重复。

技术选型

Java 中的 happens-before ordering 通过一些关键字和类提供了可靠的内存可见性和线程同步机制,这些关键字和类包括:synchronized、volatile、final、java.util.concurrent.lock|atomic。

内存中的可见部分

在这里插入图片描述
当多个线程访问共享资源时,可能会出现数据不一致的问题,这时就需要使用同步机制来解决。因此JMM推出了三个特性:可见性、有序性、原子性。
在这里插入图片描述

synchronized同步机制

synchronized 是 Java 中最基本的同步技术,它可以在多个线程之间提供原子性和可见性,保证一段代码在同一时刻只有一个线程可以执行。

保证原子性和可见性

在这里插入图片描述
使用 synchronized 时,需要指定一个锁对象,在任意时刻,最多只有一个线程可以拥有该锁对象,从而保证同一时刻只能有一个线程执行被锁定的代码块。

锁的类型和范围

synchronized 可以用来修饰普通方法、静态方法和代码块,以适应不同场景的同步需求。
在这里插入图片描述

线程的Java Monitors监视器

在Java中,每个对象都有一个内部的锁,也称为对象监视器(monitor)。synchronized 关键字就是用来获得和释放对象的监视器的。当一个线程获得了一个对象的锁,并进入了该对象的同步代码块,其他线程如果需要获取该对象的锁就会被阻塞,直到该线程释放锁为止。因此,synchronized 关键字是实现线程同步的重要手段之一。在 Java 中,每个对象都有一个监视器锁(也称为内置锁或反应锁),它可用于实现同步。

synchronized 就是通过锁来实现同步的,当一个线程获取到了锁,其他需要访问被锁住的代码块的线程会被阻塞,等待锁被释放。同时,每个对象只有一个锁,一个线程对该对象的锁拥有之后,其他访问该对象的线程将无法操作该对象的所有同步方法和同步代码块,这就能够保证了多个线程在访问共享资源时的同步。因此,对象监视器和 synchronized 锁是密不可分的。
在这里插入图片描述
该图将监视器显示为三个矩形。在中心,一个大矩形包含一个线程,即监视器的所有者。在左侧,一个小矩形包含条目集。在右边,另一个小矩形包含等待集。活动线程显示为深灰色圆圈。悬挂的线程用浅灰色的圆圈表示。

线程的可见性

volatile关键字
  1. 简化实现或者同步策略验证的时候来使用它;
  2. 确保引用对象的可见性;
  3. 标示重要的生命周期的事件,例如:开始或者关闭。
脆弱的volatile的使用条件:
  1. 写入变量不依赖变量的当前值,或者能够保证只有单一的线程修改变量的值;
  2. 变量不需要和其他变量共同参与不变约束;
  3. 访问变量时不需要其他原因需要加锁。
private volatile boolean isInterrupted = false;

在这里插入图片描述

线程:独占锁

非方法修饰符和类修饰符可以用来修饰 Java 中的各种程序元素,需要注意的是,在方法覆盖时需要添加 synchronized 修饰符。

关于经典的顺序锁问题,则是在多线程环境下,如果将两个线程安全的方法组合在一起,不一定能够保证整体的线程安全性。

另外还有一个常见的问题就是,在 Java 中当一个对象调用 getClass() 方法时,该方法会返回该对象所属的类的 Class 对象。

Object a new object();
Object b new object();
public void order(){
	synchronized(a){
	//do something
		synchronized(b){
			//do something
		}
	}
}
public void order1(){
	synchronized(b){
		//do something
		synchronized(a){
			//do something
		}
	}
}		
线程:分拆锁

在多线程编程中,为了保证数据的正确性和避免竞态条件,我们通常会使用锁来对临界区进行保护。然而,在某些情况下,线程之间的锁竞争可能会导致性能瓶颈,造成程序的性能下降。

public class ServerStatus{
public final Set<String>users new HashSet<String>();
public final Set<String>queries new HashSet<String>();
public synchronized void adduser(String u){users.add(u);
public synchronized void addQuery(String q){queries.add(q);
public synchronized void removeUser(String u)(users.remove (u);}
public synchronized void removeQuery(String q)(queries.remove(q);
}

在这种情况下,我们可以尝试将锁拆成多个细粒度的部分,分别对每个细粒度部分进行锁定,并发执行,尽量减小锁竞争范围,以提高程序的并发性和性能。这种技术就被称为“线程分拆锁”。

public class SpinOff Server Status public final Set<String>users=new HashSet<String>()public void addUser(String u){
synchronized(users) {
users.add(u)}
public void remove User(String u){
synchronized(users) {
users.remove(u)}
}

例如,如果在一个大的数据结构上进行操作,我们可以将数据结构划分为多个小的数据块,对每个数据块进行单独的锁控制和并发访问。这样可以更细粒度地控制锁的范围,减小锁的竞争,提高并发性能。

需要注意的是,在使用线程分拆锁的技术时,要确保各个锁的操作是互不干扰、没有依赖关系的,否则可能会导致死锁或者其他并发问题。此外,线程分拆锁一般需要对数据结构进行重新设计和调整,需要仔细评估和测试,以确保其可行性和有效性。

线程:分离锁
private final Object[]locks;
private static final in tN_LOCKS=4;
private final String[] share;
private into pNum;
private in tN_A NUM;
public Stripping Lock(int on,int a num) {
	opNum=on;
	N_ANUM=anum;
	share=new String[NANUM];
	locks=new Object[NLOCKS];
	for(int i=0;i<NLOCKS; i++)
		locks[i] =new Object();
}

public synchronized void put1(int indx,String k)
	share[indx]=k;//acquire the object lock
}
public void put 2(int indx, String k){
    synchronized(locks[indx号N_LOCKS] ) {
    	share[indx] =k; //acquire the corresponding lock 1
	}
}

分离锁存在的缺点之一是,对容器加锁可能会导致独占访问变得更加困难和昂贵。此外,使用分离锁可能会导致内存使用过多,例如在Action层使用ConcurrentHashMap曾因此问题导致内存使用过大,修改array后竟然单台服务器节省2G。

教父Joshua Bloch说线程

在这里插入图片描述

书籍推荐

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

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

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

相关文章

Redis客户端 - RedisSerializer

原文首更地址&#xff0c;阅读效果更佳&#xff01; Redis客户端 - RedisSerializer | CoderMast编程桅杆https://www.codermast.com/database/redis/redistemplate-redis-serializer.html 前景回顾 在上一篇中&#xff0c;我们实现了一个简单的案例&#xff0c;操作一个 St…

【22AP20 解码处理器(Hi3536AV100)】

22AP20 解码处理器(Hi3536AV100) 一、产品简介 22AP20 是针对多路高清/超高清&#xff08;1080p/4M/5M/4K&#xff09;智能 NVR 产品应用开发的新一代专业高端 SoC 芯片。22AP20 集成了 ARM Cortex-A55 八核处理器和性能强大的图像分析工具处理器&#xff0c;支持多种智能算法…

webpack无损压缩本地静态资源图片image-minimizer-webpack-plugin

开发如果项目中引用了较多图片&#xff0c;那么图片体积会比较大&#xff0c;将来请求速度比较慢。 我们可以对图片进行压缩&#xff0c;减少图片体积。 一、image-minimizer-webpack-plugin介绍 Image-minimizer-webpack-plugin是一个用于优化和压缩图片的Webpack插件。它使…

Qt5.15.2安装Android开发环境。

文章目录 1.下载并安装JDK1.1.下载1.2.安装 2.修改sdk_definitions.json文件3.QtCreator的配置3.1.设置JDK、Android SDK的路径3.2.设置openssl 现在&#xff08;20230617&#xff09;利用QtCreator来配置android开发环境还是挺方便的。基本三步搞定&#xff08;不过你要先安装…

《分布式中间件技术实战:Java版》学习笔记(一):抢红包

数据库建表 (1)red_send_record 记录用户发送了若干总金额的若干个红包。 CREATE TABLE red_send_record (id int(0) NOT NULL AUTO_INCREMENT,user_id int(0) NOT NULL COMMENT 用户id,red_packet varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL…

笔记本电脑介绍:记录生活,激发灵感

笔记本电脑是一种轻便、便携的电脑&#xff0c;它的出现改变了人们的工作和生活方式&#xff0c;它的优势在于它的小巧、轻便、便携性&#xff0c;可以满足用户的不同需求。本文将从笔记本电脑的结构、功能、优势和应用四个方面进行详细阐述。 一、笔记本电脑的结构 笔记本电…

mysql常见错误汇总

mysql常见错误汇总 列别名问题 可以在查询选择列表中使用别名为列提供 不同名称。可以使用 、 或子句中的别名来引用该列&#xff1a;GROUP BY ORDER BY HAVING SELECT SQRT(a*b) AS root FROM tbl_nameGROUP BY root HAVING root > 0;SELECT id, COUNT(*) AS cnt FROM t…

Grafana安装和实现可视化和告警

1、Grafana安装和实现可视化和告警 Prometheus UI 提供了快速验证 PromQL 以及临时可视化支持的能力&#xff0c;但其可视化能力却比较弱。一般情况下&#xff0c; 我们都用 Grafana 来实现对 Prometheus 的可视化实现。 1.1 什么是 Grafana Grafana 是一个用来展示各种各样…

【Linux】可重入函数

文章目录 前言一. 场景二. 可重入与线程安全结束语 前言 在Linux中&#xff0c;进程/线程可能因为时间片到达&#xff0c;或者其他中断&#xff0c;或者调用系统&#xff0c;需要从用户态切换到内核态&#xff0c;而内核空间会保存切换前&#xff0c;用户代码执行处的上下文&a…

环境搭建【1】VM和ubuntun 环境搭建

1.安装VMware 1.1 下载安装包 &#xff08;1&#xff09;官网下载&#xff1a;https://customerconnect.vmware.com/en/downloads/info/slug/desktop_end_user_computing/vmware_workstation_pro/16_0 &#xff08;2&#xff09;百度网盘&#xff1a;https://pan.baidu.com/s/…

5.pixi.js编写的塔防游戏(类似保卫萝卜)-子弹跟随精灵移动

游戏说明 一个用pixi.js编写的h5塔防游戏&#xff0c;可以用electron打包为exe&#xff0c;支持移动端&#xff0c;也可以用webview控件打包为app在移动端使用 环境说明 cnpm6.2.0 npm6.14.13 node12.22.7 npminstall3.28.0 yarn1.22.10 npm config list electron_mirr…

【详解】篮球记分牌硬件及代码

篮球记分牌设计 1 系统设计1.1 设计任务 1.2 性能指标要求1.2 设计思路及设计框图1.2.1设计思路1.2.2总体设计框图1.2.3电路原理图1.2.3 PCB布线图 2 主要程序模块的设计及原理2.1 外部中断0 2.2 菜单2.3 两队比分及两队犯规次数显示及修改2.3.1选择功能2.3.2修改功能2.3.3显示…

golang vscode环境报错gopls was not able to find modules in your workspace的解决方式

目录 错误提示 分析 解决方式 方法一&#xff1a;将workspace与项目路径保持一致 方案二&#xff1a;使用go work指明纳入工作区的的module 总结 错误提示 golang从老版本升级到go1.20.5后打开vscode&#xff0c;发现代码不能自动补全了&#xff0c;而且vscode跳出一下的…

dolphinscheduler创建创建租户错误

报错信息 [ERROR] 2023-06-17 17:04:10.282 org.apache.dolphinscheduler.api.exceptions.ApiExceptionHandler:[45] - 创建租户错误 org.apache.hadoop.security.AccessControlException: Permission denied: userhdfs, accessWRITE, inode"/":root:supergroup:drw…

搭建自己的 new bing网站----nginx反代(群晖,全docker版)

文章目录 1.前言&#xff1a;2. 部署过程&#xff1a;2.1.部署go-proxy-bing 项目&#xff1a;2.1.部署nginx反代&#xff1a;这两步完成实际上就可以访问了&#xff0c; 3.部署聊天服务器&#xff1a;代表链接成功&#xff01; 1.前言&#xff1a; 本篇教程全萌新向&#xff…

Qt for Android 调试遇到问题总结

一、首次编译Downloading “Gradle” 无法下载导致编译无法完成问题 解决办法&#xff1a; 1、通过地址&#xff1a;https://services.gradle.org/distributions/gradle-5.5.1-bin.zip单独下载 2、再将下载的gradle-5.5.1-bin.zip放到“C:\Users\hp\.gradle\wrapper\dists\gr…

软件工程导论期末急救包(上)

目录 什么是软件工程&#xff1f;它的目标和内容是什么&#xff1f; 软件文档作用及包含 软件过程模型 瀑布模型 快速原型模型 增量模型 螺旋模型 喷泉模型 软件生存周期 需求分析阶段的基本任务是什么&#xff1f; 可行性研究的任务是什么&#xff1f; 软件是什…

MySQL——MySQL的图形化界面工具安装与使用

作者简介&#xff1a;一名云计算网络运维人员、每天分享网络与运维的技术与干货。 座右铭&#xff1a;低头赶路&#xff0c;敬事如仪 个人主页&#xff1a;网络豆的主页​​​​​​ 目录 前言 写在前面&#xff1a; 一.DataGrip安装使用 1). 找到下载准备好的安装包&am…

2023 最新 1200 道 JAVA 面试题,囊括面试所有硬核技能

Java 面试八股文有必要背吗&#xff1f; 我的回答是&#xff1a;很有必要。你可以讨厌这种模式&#xff0c;但你一定要去背&#xff0c;因为不背你就进不了大厂。现如今&#xff0c;Java 面试的本质就是八股文&#xff0c;把八股文面试题背好&#xff0c;面试才有可能表现好。…

power gating/power switch/level shift/IR-drop

目录 1.power gating 2.level shift 3.IR-drop 1.power gating power gating 的设计重点如下&#xff1a; 1)Power Switch的设计&#xff1b; 2)Power Gating controller的设计&#xff1b; 3)retention register和isolation cell的选择及插入&#xff1b; 4)Power Gati…