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


相关推荐: 怎么制作网站设计模板图片,有电商商品详情页面的免费模板素材网站推荐吗?  如何打造高效商业网站?建站目的决定转化率  Laravel如何使用Livewire构建动态组件?(入门代码)  Android中AutoCompleteTextView自动提示  在线制作视频的网站有哪些,电脑如何制作视频短片?  javascript中对象的定义、使用以及对象和原型链操作小结  如何在万网利用已有域名快速建站?  Win11怎么设置默认图片查看器_Windows11照片应用关联设置  Laravel如何使用Socialite实现第三方登录?(微信/GitHub示例)  北京网站制作公司哪家好一点,北京租房网站有哪些?  Win11怎么设置虚拟桌面 Win11新建多桌面切换操作【技巧】  如何在浏览器中启用Flash_2025年继续使用Flash Player的方法【过时】  JavaScript如何实现继承_有哪些常用方法  如何在建站之星网店版论坛获取技术支持?  如何为不同团队 ID 动态生成多个独立按钮  Laravel怎么实现一对多关联查询_Laravel Eloquent模型关系定义与预加载【实战】  网站制作怎么样才能赚钱,用自己的电脑做服务器架设网站有什么利弊,能赚钱吗?  Android仿QQ列表左滑删除操作  Linux系统命令中screen命令详解  Laravel如何使用Blade模板引擎?(完整语法和示例)  Laravel怎么做缓存_Laravel Cache系统提升应用速度的策略与技巧  如何在自有机房高效搭建专业网站?  php嵌入式断网后怎么恢复_php检测网络重连并恢复硬件控制【操作】  如何在云指建站中生成FTP站点?  python中快速进行多个字符替换的方法小结  HTML5空格在Angular项目里怎么处理_Angular中空格的渲染问题【详解】  Laravel怎么使用Blade模板引擎_Laravel模板继承与Component组件复用【手册】  Laravel用户密码怎么加密_Laravel Hash门面使用教程  Laravel路由怎么定义_Laravel核心路由系统完全入门指南  进行网站优化必须要坚持的四大原则  Laravel如何获取当前用户信息_Laravel Auth门面获取用户ID  如何基于云服务器快速搭建个人网站?  深圳防火门网站制作公司,深圳中天明防火门怎么编码?  微信小程序 input输入框控件详解及实例(多种示例)  Laravel如何发送邮件_Laravel Mailables构建与发送邮件的简明教程  详解免费开源的DotNet二维码操作组件ThoughtWorks.QRCode(.NET组件介绍之四)  焦点电影公司作品,电影焦点结局是什么?  JavaScript如何实现类型判断_typeof和instanceof有什么区别  Laravel如何使用Guzzle调用外部接口_Laravel发起HTTP请求与JSON数据解析【详解】  儿童网站界面设计图片,中国少年儿童教育网站-怎么去注册?  佛山企业网站制作公司有哪些,沟通100网上服务官网?  如何制作公司的网站链接,公司想做一个网站,一般需要花多少钱?  如何在阿里云部署织梦网站?  网站图片在线制作软件,怎么在图片上做链接?  5种Android数据存储方式汇总  青岛网站建设如何选择本地服务器?  PHP 500报错的快速解决方法  Laravel如何从数据库删除数据_Laravel destroy和delete方法区别  Laravel Fortify是什么,和Jetstream有什么关系  专业型网站制作公司有哪些,我设计专业的,谁给推荐几个设计师兼职类的网站?