当前位置: 首页 > news >正文

论 SoC上的Linux如何拉动外部I/O

在MCU中(如classic autosr或其他RTOS),一般可以直接通过往对应的寄存器(地址转为指针)写值,
或者调用一些硬件抽象层或者驱动接口来拉动芯片提供的GPIO。
但是在Linux中,可能不会让应用层直接去访问底层的物理地址,而且配置GPIO或者其他什么IO,往往不只一个寄存器,可能是一组,比较复杂。

SoC中嵌入式Linux控制I/O需要关注的问题

SoC相较于单片机或者MCU,往往复杂得多。读芯片手册和电路板原理图的时候,需要关注很多问题,

I/O种类

目前我看到的I/O有两种,一种是SoC芯片直接提供的GPIO. 一种是通过i2c总线,挂一些I/O扩展器,来实现的外部I/O。
对于SoC板而言,可能这两种同时存在。但是他们的控制方法是不同的。

当使用了总线 I/O扩展芯片来实现外部 I/O, 那么还需要获取和阅读对应扩展芯片的手册。

设备树

需要查阅、核对、修正设备树的能力。
SoC内部的配置和体系各家各自成一套,所以才有设备树。设备树和开发板不配套,可能会造成很多问题,比如/dev下面东西不对。地址不对等等。
另外,要是内核裁剪的有问题,比如一些驱动或者文件系统没有放进来,就更麻烦了,要重新编译内核和内核模块。

GPIO

需要先确认我们需要使用的GPIO芯片,以及该端口位于该GPIO芯片的编号。

然后可以使用gpio文件系统去配置和控制对应的IO。

这里可能需要使用设备树文件来识别控制芯片和偏移。
偏移请参阅SOC的芯片手册。

下面都以TDA4论坛上的问答为例:
[FAQ] TDA4VM/DRA829/AM65xx: Linux: Configuring GPIOs

查询gpio控制芯片和设备树信息:

root@j7-evm:~# find /proc/device-tree/__symbols__/ | grep gpio
/proc/device-tree/__symbols__/main_gpio_intr
/proc/device-tree/__symbols__/main_gpio7
/proc/device-tree/__symbols__/main_gpio5
/proc/device-tree/__symbols__/wkup_gpio0
/proc/device-tree/__symbols__/main_gpio3
/proc/device-tree/__symbols__/main_gpio1
/proc/device-tree/__symbols__/gpio_keys
/proc/device-tree/__symbols__/wkup_gpio_intr
/proc/device-tree/__symbols__/main_gpio6
/proc/device-tree/__symbols__/wkup_gpio1
/proc/device-tree/__symbols__/main_gpio4
/proc/device-tree/__symbols__/main_gpio2
/proc/device-tree/__symbols__/main_gpio0root@j7-evm:~# cat /proc/device-tree/__symbols__/main_gpio0
/interconnect@100000/gpio@600000

然后对应地址来找驱动文件系统:


root@j7-evm:~# ls -la /sys/class/gpio/lrwxrwxrwx 1 root root 0 Feb 17 08:38 gpiochip84 -> ../../devices/platform/interconnect@100000/600000.gpio/gpio/gpiochip84

根据对应的地址我们发现,控制芯片是84

如果我们要控制gpio0_127。
就得到:84+127=211.

然后:

root@j7-evm:~# cd /sys/class/gpio/
root@j7-evm:/sys/class/gpio# echo 211 > export
root@j7-evm:/sys/class/gpio# cd gpio211
root@j7-evm:/sys/class/gpio/gpio211# echo out > direction
root@j7-evm:/sys/class/gpio/gpio100# echo 1 > value

Above should export the GPIO and you can do read/writes.

I2C扩展I/O

参考:
TDA4VMXEVM: USER_LED1 & USER_LED2 through I2C GPIO EXPANDER2 (TCA6424ARGJR) - Processors forum - Processors - TI E2E support forums

以TDA4通用开发板为例:

在这里插入图片描述

开发板原理图中包含GPIO扩展MAP表。
查表可知I2C0 总线,0x22芯片地址的P26 P27有两个灯(I/O)可以被用户使用。

在这里插入图片描述

从图中可知,这是一个IO扩展芯片,和SOC之间通过I2C扩展。

这里写了地址0x22。和芯片型号。

查询对应型号的芯片手册,

8.6.2 Register Descriptions

在这里插入图片描述

从datasheet中可知,寄存器0 1 2三个字节,表示各个io的读取结果。

4 5 6是配置输出内容的地方。

8 9 10,配置极性反转。目前用不到。

12 13 14,配置I/O的方向。1 是输入,0 是输出。

那我们需要点亮LED P26 P27。

就如下操作:

查看i2c地址和对应的总线号。


root@j7-evm:~# dmesg | grep i2c
[    1.082853] i2c /dev entries driver
[    1.235041] omap_i2c 40b00000.i2c: bus 0 rev0.12 at 100 kHz
[    1.235521] omap_i2c 40b10000.i2c: bus 1 rev0.12 at 100 kHz
[    1.239971] omap_i2c 42120000.i2c: bus 2 rev0.12 at 100 kHz
[    1.265639] omap_i2c 2000000.i2c: bus 3 rev0.12 at 400 kHz
[    1.266549] omap_i2c 2010000.i2c: bus 4 rev0.12 at 400 kHz
[    1.267005] omap_i2c 2020000.i2c: bus 5 rev0.12 at 100 kHz
[    1.292154] omap_i2c 2030000.i2c: bus 6 rev0.12 at 400 kHz
[    1.295636] omap_i2c 2040000.i2c: bus 7 rev0.12 at 100 kHz
[    1.296040] omap_i2c 2050000.i2c: bus 8 rev0.12 at 100 kHz
[    1.319763] omap_i2c 2060000.i2c: bus 9 rev0.12 at 400 kHzroot@j7-evm:/proc/device-tree/__symbols__# cat main_i2c0
/bus@100000/i2c@2000000

可知i2c0 的总线号是 3.

后面使用i2c 工具来操作扩展芯片的寄存器:

#查看设备
root@j7-evm:~# i2cdetect -y -r  30  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- -- 
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
20: UU -- UU -- -- -- -- -- -- -- -- -- -- -- -- -- 
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
50: -- -- -- -- -- -- -- 57 -- -- -- -- -- -- -- -- 
60: -- -- -- -- -- -- -- -- -- -- -- -- -- 6d -- -- 
70: 70 71 -- -- -- -- 76 -- #UU似乎表示这里0x20 0x22是两个内核没有使用的设备,和手册里的i2c芯片地址对应了# 读取当前寄存器内容
root@j7-evm:~# i2cdump -f -y 3 0x22 b0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f    0123456789abcdef
00: 0c 84 f1 XX 3f fd ff XX 00 00 00 XX 3b f9 ef XX    ???X??.X...X;??X
10: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX    XXXXXXXXXXXXXXXX
20: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX    XXXXXXXXXXXXXXXX
30: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX    XXXXXXXXXXXXXXXX
40: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX    XXXXXXXXXXXXXXXX
50: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX    XXXXXXXXXXXXXXXX
60: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX    XXXXXXXXXXXXXXXX
70: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX    XXXXXXXXXXXXXXXX
80: 0c 84 f1 XX 3f fd ff XX 00 00 00 XX 3b f9 ef XX    ???X??.X...X;??X
90: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX    XXXXXXXXXXXXXXXX
a0: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX    XXXXXXXXXXXXXXXX
b0: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX    XXXXXXXXXXXXXXXX
c0: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX    XXXXXXXXXXXXXXXX
d0: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX    XXXXXXXXXXXXXXXX
e0: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX    XXXXXXXXXXXXXXXX
f0: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX    XXXXXXXXXXXXXXXX# 配置P26 为输出
#P27在14号寄存器上,现在是ef .P27配为0 输出后是6Froot@j7-evm:~# i2cset -y -f 3 0x22 0x0e 0x6f
root@j7-evm:~# i2cdump -f -y 3 0x22 b0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f    0123456789abcdef
00: 0c 84 f1 XX 3f fd ff XX 00 00 00 XX 3b f9 6f XX    ???X??.X...X;?oX
10: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX    XXXXXXXXXXXXXXXX
20: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX    XXXXXXXXXXXXXXXX
30: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX    XXXXXXXXXXXXXXXX
40: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX    XXXXXXXXXXXXXXXX
50: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX    XXXXXXXXXXXXXXXX
60: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX    XXXXXXXXXXXXXXXX
70: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX    XXXXXXXXXXXXXXXX
80: 0c 84 f1 XX 3f fd ff XX 00 00 00 XX 3b f9 6f XX    ???X??.X...X;?oX
90: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX    XXXXXXXXXXXXXXXX
a0: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX    XXXXXXXXXXXXXXXX
b0: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX    XXXXXXXXXXXXXXXX
c0: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX    XXXXXXXXXXXXXXXX
d0: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX    XXXXXXXXXXXXXXXX
e0: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX    XXXXXXXXXXXXXXXX
f0: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX    XXXXXXXXXXXXXXXX#再将P26输出数据配置为0 在6号寄存器上 改成7F
root@j7-evm:~# i2cset -f -y 3 0x22 0x06 0x7F
root@j7-evm:~# i2cdump -f -y 3 0x22 b0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f    0123456789abcdef
00: 0c 84 71 XX 3f fd 7f XX 00 00 00 XX 3b f9 6f XX    ??qX???X...X;?oX
10: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX    XXXXXXXXXXXXXXXX
20: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX    XXXXXXXXXXXXXXXX
30: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX    XXXXXXXXXXXXXXXX
40: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX    XXXXXXXXXXXXXXXX
50: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX    XXXXXXXXXXXXXXXX
60: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX    XXXXXXXXXXXXXXXX
70: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX    XXXXXXXXXXXXXXXX
80: 0c 84 71 XX 3f fd 7f XX 00 00 00 XX 3b f9 6f XX    ??qX???X...X;?oX
90: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX    XXXXXXXXXXXXXXXX
a0: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX    XXXXXXXXXXXXXXXX
b0: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX    XXXXXXXXXXXXXXXX
c0: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX    XXXXXXXXXXXXXXXX
d0: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX    XXXXXXXXXXXXXXXX
e0: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX    XXXXXXXXXXXXXXXX
f0: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX    XXXXXXXXXXXXXXXX

可以看到一个灯亮了!!!

相关文章:

论 SoC上的Linux如何拉动外部I/O

在MCU中(如classic autosr或其他RTOS),一般可以直接通过往对应的寄存器(地址转为指针)写值, 或者调用一些硬件抽象层或者驱动接口来拉动芯片提供的GPIO。 但是在Linux中,可能不会让应用层直接去…...

SpringBoot项目如何部署SSL证书 (JKS格式)

1、SpringBoot项目如何部署SSL证书 (JKS格式) 1. 获取 SSL 证书和私钥 首先,你需要获取有效的 SSL 证书和私钥。SSL 证书是一种用于加密通信的数字证书,它可以通过购买商业 SSL 证书或使用免费的 Let’s Encrypt 证书获得。请确保你拥有证书文件和与之…...

成功解决:ValueError Cannot assign non-leaf Tensor to parameter ‘weight‘

成功解决:ValueError Cannot assign non-leaf Tensor to parameter ‘weight‘ 欢迎大家来到安静到无声的《模式识别与人工智能(程序与算法)》,如果对所写内容感兴趣请看模式识别与人工智能(程序与算法)系列讲解 - 总目录,同时这也可以作为大家学习的参考。欢迎订阅,优…...

面试之快速学习SQL-基础增删改查语句

1. SELECT SELECT column1,column2,column3 FROM table_name;SELECT * FROM table_name;2. SQL SELECT DISTINCT 语句 在表中,可能会包含重复值。这并不成问题,不过,有时您也许希望仅仅列出不同(distinct)的值。 SE…...

nuxt脚手架创建项目

在初始化时遇到一个依赖找不到的问题,记录一下,如有遇到同样问题的小伙伴,希望能给你们一点指引。 从安装脚手架开始,首先 一:安装nuxt脚手架 1. C盘全局安装: npm i -g create-nuxt-app 安装后可creat…...

复现原型链污染漏洞

目录 一、复现原型链污染漏洞 hackit 2018 1、创建hackit_2018.js文件 2、运行hackit_2018.js文件 3、寻找原型链漏洞 4、污染原型链 hackit 2018 1、创建hackit_2018.js文件 const express require(express) var hbs require(hbs); var bodyParser require(body-par…...

.Net6 Web Core API 配置 Autofac 封装 --- 依赖注入

目录 一、NuGet 包导入 二、Autofac 封装类 三、Autofac 使用 四、案例测试 下列封装 采取程序集注入方法, 单个依赖注入, 也适用, 可<依赖注入>的地方配置 一、NuGet 包导入 Autofac Autofac.Extensions.DependencyInjection Autofac.Extras.DynamicProxy 二、Auto…...

鸿鹄工程项目管理系统em Spring Cloud+Spring Boot+前后端分离构建工程项目管理系统 em

​ Java版工程项目管理系统 Spring CloudSpring BootMybatisVueElementUI前后端分离 功能清单如下&#xff1a; 首页 工作台&#xff1a;待办工作、消息通知、预警信息&#xff0c;点击可进入相应的列表 项目进度图表&#xff1a;选择&#xff08;总体或单个&#xff09;项目…...

【搭建PyTorch神经网络进行气温预测】

import numpy as np import pandas as pd import matplotlib.pyplot as plt import torch import torch.optim as optim import warnings warnings.filterwarnings("ignore") %matplotlib inlinefeatures pd.read_csv(temps.csv)#看看数据长什么样子 features.head…...

.Net6 Web Core API --- AOP -- log4net 封装 -- MySQL -- txt

目录 一、引入 NuGet 包 二、配置log4net.config 三、编写Log4net封装类 四、编写日志记录类 五、AOP -- 拦截器 -- 封装 六、案例编写 七、结果展示 一、引入 NuGet 包 log4net Microsoft.Extensions.Logging.Log4Net.AspNetCore MySql.Data ---- MySQL…...

【论文阅读】对抗溯源图主机入侵检测系统的模仿攻击(NDSS-2023)

作者&#xff1a;伊利诺伊大学芝加哥分校-Akul Goyal、Gang Wang、Adam Bates&#xff1b;维克森林大学-Xueyuan Han、 引用&#xff1a;Goyal A, Han X, Wang G, et al. Sometimes, You Aren’t What You Do: Mimicry Attacks against Provenance Graph Host Intrusion Detect…...

微信小程序多图片上传实用代码记录

微信小程序多图片上传实用代码记录 由于在小程序中&#xff0c;wx.uploadFile 只能一次上传一张图片&#xff0c;因此在一次需要上传多张图片的应用场景中例如商品图片上传、评论图片上传等场景下&#xff0c;不得不使用for等循环上传每一张图片&#xff0c;多次调用wx.upload…...

android实现获取系统全局对象实例

无需Context获取系统常用全局对象&#xff1a;Application&#xff0c;Activity&#xff0c;PackageManager等。 import android.app.Activity; import android.app.Application; import android.app.Service; import android.content.Context; import android.content.pm.Pac…...

viewerjs 如何新增下载图片功能(npm包补丁)

文章目录 先实现正常的效果实现下载图片改变viewerjs的build函数源码改变之后&#xff0c;执行npm i 之后node_modules源码又变回了原样 1、viwerjs所有功能都很完善&#xff0c;但唯独缺少了图片的下载 2、需求&#xff1a;在用viwerjs旋转图片后&#xff0c;可以直接下载旋转…...

基于YOLOv7开发构建MSTAR雷达影像目标检测系统

MSTAR&#xff08;Moving and Stationary Target Acquisition and Recognition&#xff09;数据集是一个基于合成孔径雷达&#xff08;Synthetic Aperture Radar&#xff0c;SAR&#xff09;图像的目标检测和识别数据集。它是针对目标检测、机器学习和模式识别算法的研究和评估…...

关于c++中mutable、const、volatile这三个关键字及对应c++与汇编示例源码

这哥三之间的关系是有趣的&#xff0c;不妨看看这个&#xff1a; cv (const and volatile) type qualifiers - cppreference.com mutable permits modification of the class member declared mutable even if the containing object is declared const. 即便一个对象是con…...

把大模型装进手机,分几步?

点击关注 文 | 姚 悦 编 | 王一粟 大模型“跑”进手机&#xff0c;AI的战火已经从“云端”烧至“移动终端”。 “进入AI时代&#xff0c;华为盘古大模型将会来助力鸿蒙生态。”8月4日&#xff0c;华为常务董事、终端BG CEO、智能汽车解决方案BU CEO 余承东介绍&#xff0c…...

c++游戏制作指南(三):c++剧情类文字游戏的制作

&#x1f37f;*★,*:.☆(&#xffe3;▽&#xffe3;)/$:*.★* &#x1f37f; &#x1f35f;欢迎来到静渊隐者的csdn博文&#xff0c;本文是c游戏制作指南的一部&#x1f35f; &#x1f355;更多文章请点击下方链接&#x1f355; &#x1f368; c游戏制作指南&#x1f3…...

Flutter系列文章-实战项目

在本篇文章中&#xff0c;我们将通过一个实际的 Flutter 应用来综合运用最近学到的知识&#xff0c;包括保存到数据库、进行 HTTP 请求等。我们将开发一个简单的天气应用&#xff0c;可以根据用户输入的城市名获取该城市的天气信息&#xff0c;并将用户查询的城市列表保存到本地…...

HCIA---TCP/UDP协议

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 目录 文章目录 一.UDP协议简介 UDP协议的特点&#xff1a; 二.TCP协议简介 TCP协议特点 三.TCP和UDP的区别 思维导图 一.UDP协议简介 UDP&#xff08;User …...

华为云AI开发平台ModelArts

华为云ModelArts&#xff1a;重塑AI开发流程的“智能引擎”与“创新加速器”&#xff01; 在人工智能浪潮席卷全球的2025年&#xff0c;企业拥抱AI的意愿空前高涨&#xff0c;但技术门槛高、流程复杂、资源投入巨大的现实&#xff0c;却让许多创新构想止步于实验室。数据科学家…...

网络六边形受到攻击

大家读完觉得有帮助记得关注和点赞&#xff01;&#xff01;&#xff01; 抽象 现代智能交通系统 &#xff08;ITS&#xff09; 的一个关键要求是能够以安全、可靠和匿名的方式从互联车辆和移动设备收集地理参考数据。Nexagon 协议建立在 IETF 定位器/ID 分离协议 &#xff08;…...

第19节 Node.js Express 框架

Express 是一个为Node.js设计的web开发框架&#xff0c;它基于nodejs平台。 Express 简介 Express是一个简洁而灵活的node.js Web应用框架, 提供了一系列强大特性帮助你创建各种Web应用&#xff0c;和丰富的HTTP工具。 使用Express可以快速地搭建一个完整功能的网站。 Expre…...

大数据学习栈记——Neo4j的安装与使用

本文介绍图数据库Neofj的安装与使用&#xff0c;操作系统&#xff1a;Ubuntu24.04&#xff0c;Neofj版本&#xff1a;2025.04.0。 Apt安装 Neofj可以进行官网安装&#xff1a;Neo4j Deployment Center - Graph Database & Analytics 我这里安装是添加软件源的方法 最新版…...

VB.net复制Ntag213卡写入UID

本示例使用的发卡器&#xff1a;https://item.taobao.com/item.htm?ftt&id615391857885 一、读取旧Ntag卡的UID和数据 Private Sub Button15_Click(sender As Object, e As EventArgs) Handles Button15.Click轻松读卡技术支持:网站:Dim i, j As IntegerDim cardidhex, …...

PHP和Node.js哪个更爽?

先说结论&#xff0c;rust完胜。 php&#xff1a;laravel&#xff0c;swoole&#xff0c;webman&#xff0c;最开始在苏宁的时候写了几年php&#xff0c;当时觉得php真的是世界上最好的语言&#xff0c;因为当初活在舒适圈里&#xff0c;不愿意跳出来&#xff0c;就好比当初活在…...

Admin.Net中的消息通信SignalR解释

定义集线器接口 IOnlineUserHub public interface IOnlineUserHub {/// 在线用户列表Task OnlineUserList(OnlineUserList context);/// 强制下线Task ForceOffline(object context);/// 发布站内消息Task PublicNotice(SysNotice context);/// 接收消息Task ReceiveMessage(…...

云启出海,智联未来|阿里云网络「企业出海」系列客户沙龙上海站圆满落地

借阿里云中企出海大会的东风&#xff0c;以**「云启出海&#xff0c;智联未来&#xff5c;打造安全可靠的出海云网络引擎」为主题的阿里云企业出海客户沙龙云网络&安全专场于5.28日下午在上海顺利举办&#xff0c;现场吸引了来自携程、小红书、米哈游、哔哩哔哩、波克城市、…...

3.3.1_1 检错编码(奇偶校验码)

从这节课开始&#xff0c;我们会探讨数据链路层的差错控制功能&#xff0c;差错控制功能的主要目标是要发现并且解决一个帧内部的位错误&#xff0c;我们需要使用特殊的编码技术去发现帧内部的位错误&#xff0c;当我们发现位错误之后&#xff0c;通常来说有两种解决方案。第一…...

线程同步:确保多线程程序的安全与高效!

全文目录&#xff1a; 开篇语前序前言第一部分&#xff1a;线程同步的概念与问题1.1 线程同步的概念1.2 线程同步的问题1.3 线程同步的解决方案 第二部分&#xff1a;synchronized关键字的使用2.1 使用 synchronized修饰方法2.2 使用 synchronized修饰代码块 第三部分&#xff…...