gpt4 book ai didi

java - 多线程可见性和原子性

转载 作者:行者123 更新时间:2023-11-30 06:19:59 26 4
gpt4 key购买 nike

我正在研究 volatile 关键字,阅读它,在那里我读到 volatile 关键字保证可见性而不是原子性,现在可见性是一个线程中所做的更改立即对另一个线程可见,所以为什么我们需要使用原子整数或原子 boolean 值..它的需要是什么,有人可以用一个常见的 volatile 用法示例,以及可见性和原子性的差异

来解释我吗

最佳答案

定义

一个操作是原子的,如果任何其他线程认为它已经完全发生,或者根本没有发生。

一个操作对另一个线程可见,如果那个线程认为它已经发生。

原子性有用性的经典示例是将钱存入银行帐户的操作:

synchronized void deposit(int dollars) {
balance = balance + dollars;
}

如果该操作不是原子操作,则想要同时将钱存入同一帐户的两个线程(T1 和 T2)可以按如下方式执行

T1 reads balance and adds dollars
T2 reads balance and adds dollars
T1 writes the result to balance
T2 writes the result to balance

这是不正确的,因为 T1 存入的钱不计入余额。

可见性有用性的经典示例是将信息从一个线程传递到另一个线程。例如,用户界面线程可能会将命令传递给后台线程。

volatile的含义

volatile 使写入(或读取)变量成为原子,即使它们是 longdouble 类型。

写入 volatile 变量对于随后从该变量读取的所有线程都是可见的。

也就是说,我们可以使用volatile将信息传递给另一个线程,例如:

volatile boolean shouldBeRunning = true;

void stop() { // invoked by T1
shouldBeRunning = false;
}

void run() { // invoked by T2
while (shouldBeRunning) {
doWork();
}
}

AtomicBoolean的优势

正如我们在上面看到的,我们可以通过声明 volatile 来使写入(或读取)boolean 成为原子操作。但是,如果我们想进行更大的操作,例如

void pauseOrResume() {
paused = !paused;
}

atomic,声明 paused volatile 是不够的,因为两个线程 T1 和 T2 可以同时执行 pauseOrResume,如下所示:

T1 reads paused (false) and negates it (true)
T2 reads paused (false) and negates it (true)
T1 writes its result (true)
T2 writes its result (true)

使用原子 boolean 值,我们可以防止这种情况发生:

void pauseOrResume() {
boolean pausedBefore = paused.get();
if (!paused.compareAndSet(pausedBefore, !pausedBefore)) {
pauseOrResume();
}
}

关于java - 多线程可见性和原子性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22421490/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com