Java多线程并发编程 并发三大要素
发布时间 - 2026-01-11 01:14:27 点击率:次一、原子性

原子,一个不可再被分割的颗粒。原子性,指的是一个或多个不能再被分割的操作。
int i = 1; // 原子操作
i++; // 非原子操作,从主内存读取 i 到线程工作内存,进行 +1,再把 i 写到朱内存。
虽然读取和写入都是原子操作,但合起来就不属于原子操作,我们又叫这种为“复合操作”。
我们可以用synchronized 或 Lock 来把这个复合操作“变成”原子操作。
例子:
private synchronized void increase(){
i++;
}
或
private int i = 0;
Lock mLock = new ReentrantLock();
private void increase() {
mLock.lock();
try {
i++;
} finally{
mLock.unlock();
}
}
这样我们就可以把这个一个方法看做一个整体,一个不可分割的整体。
除此之前,我们还可以用java.util.concurrent.atomic里的原子变量类,可以确保所有对计数器状态访问的操作都是原子的。
例子:
AtomicInteger mAtomicInteger = new AtomicInteger(0);
private void increase(){
mAtomicInteger.incrementAndGet();
}
二、可见性
当多线程访问某一个(同一个)变量时,其中一条线程对此变量作出修改,其他线程可以立刻读取到最新修改后的变量。
int i = 0;
// 线程 1 执行
i++;
// 线程 2 执行
System.out.print("i=" + i);
即使是在执行完线程里的 i++ 后再执行线程 2,线程 2 的输入结果也会有 2 个种情况,一个是 0 和 1。
因为 i++ 在线程 1(CPU1)中做完了运算,并没有立刻更新到主内存当中,而线程 2(CPU2)就去主内存当中读取并打印,此时打印的就是 0。
synchronized和Lock能够保证可见性。
另外volatile关键字也可以解决这个问题(下一篇会讲到)。
三、有序性
我们都知道处理器为了拥有更好的运算效率,会自动优化、排序执行我们写的代码,但会确保执行结果不变。
例子:
int a = 0; // 语句 1 int b = 0; // 语句 2 i++; // 语句 3 b++; // 语句 4
这一段代码的执行顺序很有可能不是按上面的 1、2、3、4 来依次执行,因为 1 和 2 没有数据依赖,3 和 4 没有数据依赖, 2、1、4、3 这样来执行可以吗?完全没问题,处理器会自动帮我们排序。
在单线程看来并没有什么问题,但在多线程则很容易出现问题。
再来个例子:
// 线程 1
init();
inited = true;
// 线程 2
while(inited){
work();
}
init(); 与 inited = true; 并没有数据的依赖,在单线程看来,如果把两句的代码调换好像也不会出现问题。
但此时处于一个多线程的环境,而处理器真的把这两句代码重新排序,那问题就出现了,若线程 1 先执行 inited = true; 此时,init() 并没有执行,线程 2 就已经开始调用 work() 方法,此时很可能造成一些奔溃或其他 BUG 的出现。
synchronized和Lock能确保原子性,能让多线程执行代码的时候依次按顺序执行,自然就具有有序性。
而volatile关键字也可以解决这个问题,volatile 关键字可以保证有序性,让处理器不会把这行代码进行优化排序。
# Java多线程
# 并发编程
# Java并发编程示例(一):线程的创建和执行
# Java并发编程示例(六):等待线程执行终止
# Java并发编程之显示锁ReentrantLock和ReadWriteLock读写锁
# Java并发编程之栅栏(CyclicBarrier)实例介绍
# Java并发编程示例(二):获取和设置线程信息
# Java并发编程示例(七):守护线程的创建和运行
# Java并发编程示例(十):线程组
# Java并发编程总结——慎用CAS详解
# 理解Java多线程之并发编程
# 多线程
# 都是
# 可以用
# 两句
# 解决这个问题
# 单线程
# 是在
# 见性
# 会有
# 多个
# 就不
# 但在
# 很容易
# 能让
# 再来
# 很可能
# 或其他
# 就去
# 已经开始
# 写到
相关栏目:
【
网站优化151355 】
【
网络推广146373 】
【
网络技术251813 】
【
AI营销90571 】
相关推荐:
javascript中数组(Array)对象和字符串(String)对象的常用方法总结
Laravel如何处理JSON字段_Eloquent原生JSON字段类型操作教程
如何用手机制作网站和网页,手机移动端的网站能制作成中英双语的吗?
Laravel用户密码怎么加密_Laravel Hash门面使用教程
手机钓鱼网站怎么制作视频,怎样拦截钓鱼网站。怎么办?
Laravel如何发送系统通知_Laravel Notifications实现多渠道消息通知
如何在景安服务器上快速搭建个人网站?
太平洋网站制作公司,网络用语太平洋是什么意思?
网站设计制作书签怎么做,怎样将网页添加到书签/主页书签/桌面?
学生网站制作软件,一个12岁的学生写小说,应该去什么样的网站?
移动端手机网站制作软件,掌上时代,移动端网站的谷歌SEO该如何做?
阿里云高弹*务器配置方案|支持分布式架构与多节点部署
Laravel如何创建自定义Artisan命令?(代码示例)
Laravel如何理解并使用服务容器(Service Container)_Laravel依赖注入与容器绑定说明
Laravel怎么进行数据库事务处理_Laravel DB Facade事务操作确保数据一致性
Android okhttputils现在进度显示实例代码
Laravel如何处理跨站请求伪造(CSRF)保护_Laravel表单安全机制与令牌校验
js代码实现下拉菜单【推荐】
Laravel如何记录自定义日志?(Log频道配置)
简单实现jsp分页
Laravel如何使用Telescope进行调试?(安装和使用教程)
php静态变量怎么调试_php静态变量作用域调试技巧【解答】
标题:Vue + Vuex 项目中正确使用 JWT 进行身份认证的实践指南
Python数据仓库与ETL构建实战_Airflow调度流程详解
PHP的CURL方法curl_setopt()函数案例介绍(抓取网页,POST数据)
javascript和jQuery中的AJAX技术详解【包含AJAX各种跨域技术】
电视网站制作tvbox接口,云海电视怎样自定义添加电视源?
Laravel如何创建自定义Facades?(详细步骤)
Win11怎么开启自动HDR画质_Windows11显示设置HDR选项
如何在云主机上快速搭建多站点网站?
Laravel怎么实现搜索高亮功能_Laravel结合Scout与Algolia全文检索【实战】
JavaScript常见的五种数组去重的方式
Laravel如何实现本地化和多语言支持_Laravel多语言配置与翻译文件管理
网站建设保证美观性,需要考虑的几点问题!
如何快速查询域名建站关键信息?
网站制作公司哪里好做,成都网站制作公司哪家做得比较好,更正规?
Laravel模型关联查询教程_Laravel Eloquent一对多关联写法
EditPlus 正则表达式 实战(3)
如何用AI帮你把自己的生活经历写成一个有趣的故事?
如何用低价快速搭建高质量网站?
教学论文网站制作软件有哪些,写论文用什么软件
?
如何选择可靠的免备案建站服务器?
Laravel如何与Inertia.js和Vue/React构建现代单页应用
如何用VPS主机快速搭建个人网站?
Windows家庭版如何开启组策略(gpedit.msc)?(安装方法)
Laravel怎么集成Log日志记录_Laravel单文件与每日日志配置及自定义通道【详解】
Laravel storage目录权限问题_Laravel文件写入权限设置
如何快速查询网址的建站时间与历史轨迹?
Laravel集合Collection怎么用_Laravel集合常用函数详解
Laravel如何使用Blade组件和插槽?(Component代码示例)

