0

0

Java 竞态条件和临界段

黄舟

黄舟

发布时间:2017-02-28 10:35:36

|

1363人浏览过

|

来源于php中文网

原创

一个竞态条件是一个特殊的条件,可能发生在一个临界部分的内部(critical section)。一个临界部分是一段正在被多线程执行的代码,以及线程执行的顺序对于临界部分并发执行的结果产生影响。

当多线程执行一个临界段的结果依赖线程执行的顺序可能是不同的,这个临界段包含一个竞态条件。这个竞态条件的词条源于这个线程正在竞速通过这个临界段的暗喻,并且这个竞争的结果影响着执行这个临界段的结果。

这个可能听起来有点复杂,以至于我将会在下面的部分详细阐述关于竞态条件和临界段。

临界段(Critical Sections)

在相同的应用内部运行不止一个线程不会被他自己引起问题。当多个线程访问相同的资源问题就会出现。例如相同的内存(变量,数组,或者对象),系统(数据库,web服务)或者文件。

立即学习Java免费学习笔记(深入)”;

事实上,如果一个或者多个线程写这些资源的时候问题会出现。让多个线程读取相同的资源是安全的,只要资源不会改变。

这里有一个例子,如果多个线程同事执行可能会失败:

 public class Counter {

     protected long count = 0;

     public void add(long value){
         this.count = this.count + value;
     }
  }


想象下如果线程A和B正在执行相同的Counter类的实例的add方法。这里没有办法知道操作系统什么时间会在线程之间切换。add方法中的代码不会被java虚拟机作为单独的原子指令执行。而是作为一系列的更小的指令集执行,跟这个类似:

  1. 从内存中读取this.count值进入寄存器。

  2. 增加value值到寄存器。

  3. 将寄存器中的值写回内存。

观察线程A和B混合执行会发生什么:

       this.count = 0;

   A:  Reads this.count into a register (0)
   B:  Reads this.count into a register (0)
   B:  Adds value 2 to register
   B:  Writes register value (2) back to memory. this.count now equals 2
   A:  Adds value 3 to register
   A:  Writes register value (3) back to memory. this.count now equals 3


这两个线程想添加2和3到counter中。因此这两个线程执行完之后的值应该是5。然而,因为这两个线程执行时交叉的,因此结果以不同而结束。

在上面提到的执行顺序的例子中,两个线程都从内存中读取到0这个值。然后他们添加他们各自的值,2和3到那个值中去,然后把这个结果写回到内存中。代替5,在this.count中留下的值将会是最后的那个线程写给他的那个值。在上面的例子中是线程A,但是他也可能是线程B。

在临界段中的竞态条件

在上面的那个例子中的add方法的代码中包含了一个临界段。当多个线程执行这个临界段的时候,竞态条件就会发生了。

AI智研社
AI智研社

AI智研社是一个专注于人工智能领域的综合性平台

下载

更正式的讲,两个线程的这种情形竞争着相同的资源,资源被访问的顺序是重要的,它被称为竞态条件。一个代码部分导致竞态条件就会被称之为临界段。

预防竞态条件

为了防止竞态条件的发生,你必须确保被执行的临界段作为一个原子指令被执行。那就意味着一旦一个单独的线程在执行它,其他的线程就不能执行它直到第一个线程已经离开了这个临界段。

竞态条件可以通过在临界段中使用线程同步的方式去避免。线程同步可以使用一个Java代码的同步锁去获取。线程同步也可以使用其他的同步概念去获取,像锁或者像java.util.concurrent.atomic.AtomicInteger的原子变量。

临界段的吞吐量

对于更小的临界段使得整个临界段的一个同步锁可能会工作。但是,对于更大的临界段,去把它分解成更小的临界段是更有意义的,使得允许多线程去执行每一个更小的临界段。整个就可能降低共享资源的竞争,以及增加整个临界段的吞吐量。

这里有一个非常简单的Java实例:

public class TwoSums {
    
    private int sum1 = 0;
    private int sum2 = 0;
    
    public void add(int val1, int val2){
        synchronized(this){
            this.sum1 += val1;   
            this.sum2 += val2;
        }
    }
}


注意这个add方法是怎样往这两个sum变量中添加值得。为了预防竞态条件,在内部执行的求和有一个Java同步锁。伴随着这个实现,同时只能有一个线程可以执行这个求和。

然而,因为这两个sum变量是相互独立的,你可以把他们分离成两个分离的同步锁,像这样:

public class TwoSums {
    
    private int sum1 = 0;
    private int sum2 = 0;
    
    public void add(int val1, int val2){
        synchronized(this){
            this.sum1 += val1;   
        }
        synchronized(this){
            this.sum2 += val2;
        }
    }
}


注意,两个线程可以同时执行这个add方法。一个线程获取到第一个同步锁,另外一个线程获取第二个同步锁。这种方式,线程之间将会等待的更少时间。

当然,这个例子是非常简单的。在真正的生活中,临界段分离的共享资源可能会更加复杂的,并且需要更多的执行顺序可能性的分析。

 以上就是Java 竞态条件和临界段的内容,更多相关内容请关注PHP中文网(www.php.cn)!

相关文章

java速学教程(入门到精通)
java速学教程(入门到精通)

java怎么学习?java怎么入门?java在哪学?java怎么学才快?不用担心,这里为大家提供了java速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
C++ 设计模式与软件架构
C++ 设计模式与软件架构

本专题深入讲解 C++ 中的常见设计模式与架构优化,包括单例模式、工厂模式、观察者模式、策略模式、命令模式等,结合实际案例展示如何在 C++ 项目中应用这些模式提升代码可维护性与扩展性。通过案例分析,帮助开发者掌握 如何运用设计模式构建高质量的软件架构,提升系统的灵活性与可扩展性。

14

2026.01.30

c++ 字符串格式化
c++ 字符串格式化

本专题整合了c++字符串格式化用法、输出技巧、实践等等内容,阅读专题下面的文章了解更多详细内容。

9

2026.01.30

java 字符串格式化
java 字符串格式化

本专题整合了java如何进行字符串格式化相关教程、使用解析、方法详解等等内容。阅读专题下面的文章了解更多详细教程。

12

2026.01.30

python 字符串格式化
python 字符串格式化

本专题整合了python字符串格式化教程、实践、方法、进阶等等相关内容,阅读专题下面的文章了解更多详细操作。

4

2026.01.30

java入门学习合集
java入门学习合集

本专题整合了java入门学习指南、初学者项目实战、入门到精通等等内容,阅读专题下面的文章了解更多详细学习方法。

20

2026.01.29

java配置环境变量教程合集
java配置环境变量教程合集

本专题整合了java配置环境变量设置、步骤、安装jdk、避免冲突等等相关内容,阅读专题下面的文章了解更多详细操作。

18

2026.01.29

java成品学习网站推荐大全
java成品学习网站推荐大全

本专题整合了java成品网站、在线成品网站源码、源码入口等等相关内容,阅读专题下面的文章了解更多详细推荐内容。

19

2026.01.29

Java字符串处理使用教程合集
Java字符串处理使用教程合集

本专题整合了Java字符串截取、处理、使用、实战等等教程内容,阅读专题下面的文章了解详细操作教程。

3

2026.01.29

Java空对象相关教程合集
Java空对象相关教程合集

本专题整合了Java空对象相关教程,阅读专题下面的文章了解更多详细内容。

6

2026.01.29

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Kotlin 教程
Kotlin 教程

共23课时 | 3万人学习

C# 教程
C# 教程

共94课时 | 8万人学习

Java 教程
Java 教程

共578课时 | 53.6万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号