首页  >  文章  >  Java  >  多线程:工程师的关键概念 - 第 1 部分

多线程:工程师的关键概念 - 第 1 部分

DDD
DDD原创
2024-09-30 10:21:20230浏览

Multithreading : Key Concepts for Engineers - Part 1

了解关键的多线程概念对于软件开发人员至关重要,因为它不仅可以增强技能,还可以直接影响应用程序开发、可扩展性和软件解决方案的整体质量。

原子性

在多线程环境中,原子操作确保一个线程可以执行一系列操作,而不会被其他线程中断。多个线程可能会尝试同时读取或写入共享数据。如果没有原子性,并发修改可能会导致不一致或意外的结果,通常称为竞争条件。

Java 规范保证“读”和“写”是原子操作而不是它们的组合。因此,根据规范,“读取、加 1,然后将结果写回”的操作不是原子操作。此类操作称为复合操作,就我们代码中的使用而言,它们通常需要是原子的。

原子操作示例:

  1. 递增计数器:如果两个线程在没有原子性的情况下同时递增计数器,则它们可能都读取相同的值并写回相同的递增值,从而导致丢失一个递增。

  2. 更新共享变量:如果一个线程正在读取一个值,而另一个线程正在修改它,如果没有原子性,读取线程可能会得到不一致的值。

实现原子性:

  • 原子类:许多编程语言都提供原子类(例如 Java 中的 AtomicInteger),它们封装了保证原子性的操作。

  • 同步方法/块:在Java等语言中,您可以使用synchronized关键字来确保一次只有一个线程可以执行一段代码或一个方法。

  • :使用显式锁(例如 Java 中的 ReentrantLock)来管理对共享资源的访问。

好处

  • 性能: java.util.concurrent.atomic 中的类还提供了无锁的方式来保证线程安全,使其成为许多场景下的首选。
  • 简单性:使用原子类可以简化代码,因为开发人员不需要管理锁,可以专注于程序的逻辑。
  • 线程安全:原子操作确保变量在多个线程中安全更新,而不存在数据损坏或竞争条件的风险。

不变性

不变性是指对象在创建后其状态无法修改的属性。在编程中,不可变对象是那些一旦初始化就不能更改或改变的对象。不是修改不可变的对象,而是创建一个具有所需更改的新对象。

不可变意味着一旦对象的构造函数完成执行,该实例就无法更改。

不可变对象的特征

  • 无状态变化:创建不可变对象后,其状态(属性或字段)在其整个生命周期中保持不变。

  • 线程安全:不可变对象可以在多个线程之间安全共享,无需同步,因为它们无法修改。

  • 哈希码稳定性: 不可变对象的哈希码在其整个生命周期中保持不变,使其适合在基于哈希的集合(如 HashMap 或 HashSet)中使用。

实现不变性:

  • 记录的使用(在 Java 14 中):在 Java 中,记录功能提供了一种创建不可变数据类的简洁方法。
public record ImmutablePoint(int x, int y) {}
  • 使用不可变数据结构:利用编程语言或库提供的现有不可变数据结构,例如:
  1. Java: Collections.unmodifyingList()、List.of()、Set.of()

  2. C#: System.Collections.Immutable 中的 ImmutableList、ImmutableArray

  3. Python:元组本质上是不可变的。

  • 使用 Final 字段: 将类的字段声明为 Final。这确保了在对象构造期间只能分配字段一次。

  • 无 Setter: 避免为可变字段提供 setter 方法。这可以防止外部代码在构造对象后更改对象的状态。

public final class ImmutablePoint {
    private final int x;
    private final int y;

    public ImmutablePoint(int x, int y) {
        this.x = x;
        this.y = y;
    }

    public int getX() {
        return x;
    }

    public int getY() {
        return y;
    }
}
  • Static Factory Methods: Instead of providing a public constructor, use static factory methods that return new instances of the object, making it clear that the state cannot be changed

  • Builder Pattern (for complex objects): For objects that require many parameters, use the builder pattern to create immutable objects. The builder accumulates the parameters and constructs an immutable instance at the end.

Benefits

  • Concurrency: If the internal structure of an immutable object is valid, it will always be valid. There's no chance that different threads can create an invalid state within that object. Hence, immutable objects are Thread Safe.

  • Garbage collection: It's much easier for the garbage collector to make logical decisions about immutable objects.

Outro

Arming yourself with this knowledge not only enhances your ability to write high-performance code but also prepares you for the challenges of modern software development, where responsiveness and scalability are paramount. As you continue your journey into the world of multithreading, remember that each concept you master will contribute to your growth as a developer and your capacity to create applications that meet and exceed user expectations.

Stay tuned as we will focus on starvation, deadlock, race-condition, OS scheduling and much more in upcoming write-up, that would elevate your programming skills and boost your career!

References

A huge thanks to the online documentation, community and all the resources available that made this write-up possible.

  1. Info-graphic
  2. Understanding Basic Multithreading Concepts
  3. Atomicity
  4. What is immutable

Disclaimer: This article is AI-assisted. The article structure and idea list are 100% manually curated and researched. I proofread all AI-generated texts to ensure information accuracy and to add some contexts

以上是多线程:工程师的关键概念 - 第 1 部分的详细内容。更多信息请关注PHP中文网其他相关文章!

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