Java Concurrencyin Practice 并发编程实践系列 第二章 线程安全 Thread Safety 上

简介: Java Concurrencyin Practice 并发编程实践系列 第二章 线程安全 Thread Safety 上

Chapter 2: Thread Safety

第二章,主要讲的是线程安全的问题,及解决方法,现在写的是如何去理解线程安全

Perhaps surprisingly, concurrent programming isn’t so much about threads or locks, any more than civil engineering is about rivets and I-beams. Of course, building bridges that don’t fall down requires the correct use of a lot of rivets and I-beams, just as building concurrent programs require the correct use of threads and locks. But these are just mechanisms—means to an end. Writing thread-safe code is, at its core, about managing access to state, and in particular to shared, mutable state.

这句话的意思是,尽管并发编程涉及到线程和锁等概念,但它的本质并不局限于这些具体的实现细节,就像土木工程并不仅仅关乎铆钉和I型钢梁一样。

这句话的目的是提醒人们,对于并发编程来说,更重要的是理解并解决并发编程所带来的挑战和问题,而不仅仅局限于线程和锁的使用。并发编程涉及到如何设计并发安全的算法、如何管理共享资源、如何处理竞争条件等等。类似地,土木工程涉及到设计建造稳固的结构、解决土地利用问题、考虑自然环境等方面。

因此,理解并发编程应该超越具体的线程和锁的细节,而是注重在整体设计和解决问题的层面上进行思考和处理。这样才能更好地应对并发编程的挑战,并开发出高效、可靠的并发程序。

threads and locks. But these are just mechanisms—means to an end.

线程和锁等并发编程的机制只是实现并发编程的手段,它们并不是目标的终点。

并发编程的目标是解决问题、提高性能、改善用户体验等。线程和锁等机制只是为了支持实现这些目标而存在,它们是一种工具,通过合理的使用来达到预期的效果。

Writing thread-safe code is, at its core, about managing access to state, and in particular to shared, mutable state.

编写线程安全的代码,在其核心是管理对状态的访问,特别是对共享的、可变的状态的访问。

在并发环境下,多个线程可能同时访问和修改共享的状态,如果没有适当的管理,就会产生数据竞争和不一致的结果。

Informally, an object’s state is its data, stored in state variables such as instance or static fields.

An object’s state may include fields from other, dependent objects;

a HashMap’s state is partially stored in the HashMap object itself, but also in many Map.Entry objects.

An object’s state encompasses any data that can affect its externally visible behavior.

(instance fields, static fields: 实例字段/实例域/实例变量, 静态字段/静态域/静态变量

有时候直接看英文原版会比看翻译会更明白一点,虽然阅读过程会比较曲折,但尽量阅读。)

object’s state指的是它的数据,存储在状态变量中,例如实例变量或静态变量。(object’s state约等于object instance fields, static fields )

对象的状态可能包括来自其他相关对象的字段;例如,HashMap的状态部分存储在HashMap对象本身中,但也存储在许多Map.Entry对象中。object’s state包括所有可能影响其对外可见行为的数据。(其实就算翻译了,还是有点看不懂的。直接举例吧。)

public class Counter {
    private int count;
    public void increment() {
        count++;
    }
    public int getCount() {
        return count;
    }
}

在这个例子中,计数器 object’s state 就是它的count字段的值。

该对象的行为取决于该状态,当调用increment方法时,状态会发生变化。

Counter Object:

  • State Variables: count (an integer field)
  • State: The value of the count field
  • Behavior: The increment() method increases the value of count, and the getCount() method returns the current value of count.

In this examples, the state of an object refers to its internal data stored in state variables. The behavior of the object depends on its state, and various methods can modify the state to achieve different functionality. Managing shared mutable state correctly is crucial in concurrent programming to ensure thread safety and proper concurrent operations.

By shared, we mean that a variable could be accessed by multiple threads;

by mutable, we mean that its value could change during its lifetime.

We may talk about thread safety as if it were about code, but what we are really trying to do is protect data from uncontrolled concurrent access.

Whether an object needs to be thread-safe depends on whether it will be accessed from multiple threads. This is a property of how the object is used in a program, not what it does. Making an object thread-safe requires using synchronization to coordinate access to its mutable state; failing to do so could result in data corruption and other undesirable consequences

By shared, we mean that a variable could be accessed by multiple threads;

multiple:与等于 n多个。variable:变量(变来变去的,百变怪)

by mutable, we mean that its value could change during its lifetime.

during its lifetime 在生命周期内/存活周期内等

这两句都是解释前面这个单词在本文的意思。

We may talk about thread safety as if it were about code, but what we are really trying to do is protect data from uncontrolled concurrent access.

我们讨论的线程安全性好像是关于代码的,但是我们真正要做的,是在不可控制的并发访问中保护数据

这句话是重点,编写线程安全的代码,真正要做的,其实是对object’s state的并发安全。而不是所有代码。

在工作中,分辨出哪些是常规代码,哪些是需要并发的,具体仔细到某一段逻辑或字段。

This is a property of how the object is used in a program, not what it does.

对象的状态是由其在程序中的使用方式决定的,而不是定义其目的或功能。

换句话说,对象的状态是指存储在其状态变量中的值,在对象被操作或与之交互时可以随着时间变化。状态表示对象在任何给定时刻的当前数据快照。

另一方面,对象的行为是指其可以执行的操作或方法,以及它对方法调用的响应方式。行为由对象的方法和其实现决定。

这句话强调了对象的状态是如何在程序执行中被使用、修改或访问而产生影响的,而行为则关注对象能做什么以及它在方法调用时如何响应。

总而言之,这句话强调了对象状态(由数据决定)与对象行为(由方法决定)之间的区别,并强调了对象的状态是由其在程序中的使用方式所影响的。

Making an object thread-safe requires using synchronization to coordinate access to its mutable state; failing to do so could result in data corruption and other undesirable consequences.

确保对象的线程安全性需要使用同步机制来协调对其可变状态的访问;如果不这样做,可能会导致数据损坏和其他不良后果。

当多个线程同时访问一个对象的可变状态时,如果没有适当的同步机制来保证线程间的协调,可能会发生以下问题:

  • 竞态条件(Race condition):多个线程同时修改对象的状态,导致结果依赖于执行的顺序,可能产生不确定的结果。
  • 数据不一致(Data inconsistency):多个线程同时读取和修改对象的状态,导致数据出现错误或不一致的情况。
  • 内存可见性问题(Memory visibility problem):多个线程在各自的缓存中保存对象的副本,没有及时将修改后的值刷新到主内存,导致其他线程无法看到最新的状态。

没完待续……

相关文章
|
2天前
|
监控 Java
java异步判断线程池所有任务是否执行完
通过上述步骤,您可以在Java中实现异步判断线程池所有任务是否执行完毕。这种方法使用了 `CompletionService`来监控任务的完成情况,并通过一个独立线程异步检查所有任务的执行状态。这种设计不仅简洁高效,还能确保在大量任务处理时程序的稳定性和可维护性。希望本文能为您的开发工作提供实用的指导和帮助。
32 17
|
12天前
|
Java
Java—多线程实现生产消费者
本文介绍了多线程实现生产消费者模式的三个版本。Version1包含四个类:`Producer`(生产者)、`Consumer`(消费者)、`Resource`(公共资源)和`TestMain`(测试类)。通过`synchronized`和`wait/notify`机制控制线程同步,但存在多个生产者或消费者时可能出现多次生产和消费的问题。 Version2将`if`改为`while`,解决了多次生产和消费的问题,但仍可能因`notify()`随机唤醒线程而导致死锁。因此,引入了`notifyAll()`来唤醒所有等待线程,但这会带来性能问题。
Java—多线程实现生产消费者
|
14天前
|
安全 Java Kotlin
Java多线程——synchronized、volatile 保障可见性
Java多线程中,`synchronized` 和 `volatile` 关键字用于保障可见性。`synchronized` 保证原子性、可见性和有序性,通过锁机制确保线程安全;`volatile` 仅保证可见性和有序性,不保证原子性。代码示例展示了如何使用 `synchronized` 和 `volatile` 解决主线程无法感知子线程修改共享变量的问题。总结:`volatile` 确保不同线程对共享变量操作的可见性,使一个线程修改后,其他线程能立即看到最新值。
|
14天前
|
消息中间件 缓存 安全
Java多线程是什么
Java多线程简介:本文介绍了Java中常见的线程池类型,包括`newCachedThreadPool`(适用于短期异步任务)、`newFixedThreadPool`(适用于固定数量的长期任务)、`newScheduledThreadPool`(支持定时和周期性任务)以及`newSingleThreadExecutor`(保证任务顺序执行)。同时,文章还讲解了Java中的锁机制,如`synchronized`关键字、CAS操作及其实现方式,并详细描述了可重入锁`ReentrantLock`和读写锁`ReadWriteLock`的工作原理与应用场景。
|
15天前
|
安全 Java 编译器
深入理解Java中synchronized三种使用方式:助您写出线程安全的代码
`synchronized` 是 Java 中的关键字,用于实现线程同步,确保多个线程互斥访问共享资源。它通过内置的监视器锁机制,防止多个线程同时执行被 `synchronized` 修饰的方法或代码块。`synchronized` 可以修饰非静态方法、静态方法和代码块,分别锁定实例对象、类对象或指定的对象。其底层原理基于 JVM 的指令和对象的监视器,JDK 1.6 后引入了偏向锁、轻量级锁等优化措施,提高了性能。
41 3
|
15天前
|
NoSQL Redis
单线程传奇Redis,为何引入多线程?
Redis 4.0 引入多线程支持,主要用于后台对象删除、处理阻塞命令和网络 I/O 等操作,以提高并发性和性能。尽管如此,Redis 仍保留单线程执行模型处理客户端请求,确保高效性和简单性。多线程仅用于优化后台任务,如异步删除过期对象和分担读写操作,从而提升整体性能。
42 1
|
3月前
|
存储 消息中间件 资源调度
C++ 多线程之初识多线程
这篇文章介绍了C++多线程的基本概念,包括进程和线程的定义、并发的实现方式,以及如何在C++中创建和管理线程,包括使用`std::thread`库、线程的join和detach方法,并通过示例代码展示了如何创建和使用多线程。
65 1
|
3月前
|
Java 开发者
在Java多线程编程中,创建线程的方法有两种:继承Thread类和实现Runnable接口
【10月更文挑战第20天】在Java多线程编程中,创建线程的方法有两种:继承Thread类和实现Runnable接口。本文揭示了这两种方式的微妙差异和潜在陷阱,帮助你更好地理解和选择适合项目需求的线程创建方式。
43 3
|
3月前
|
Java 开发者
在Java多线程编程中,选择合适的线程创建方法至关重要
【10月更文挑战第20天】在Java多线程编程中,选择合适的线程创建方法至关重要。本文通过案例分析,探讨了继承Thread类和实现Runnable接口两种方法的优缺点及适用场景,帮助开发者做出明智的选择。
28 2
|
3月前
|
Java
Java中多线程编程的基本概念和创建线程的两种主要方式:继承Thread类和实现Runnable接口
【10月更文挑战第20天】《JAVA多线程深度解析:线程的创建之路》介绍了Java中多线程编程的基本概念和创建线程的两种主要方式:继承Thread类和实现Runnable接口。文章详细讲解了每种方式的实现方法、优缺点及适用场景,帮助读者更好地理解和掌握多线程编程技术,为复杂任务的高效处理奠定基础。
45 2