gpt4 book ai didi

java - 当 set 在 Java 中已经是原子的时,为什么我们需要 compareAndSet?

转载 作者:塔克拉玛干 更新时间:2023-11-01 21:53:46 27 4
gpt4 key购买 nike

因为 Atomic 意味着线程安全。当 .set() 本身在 Java 中是原子和线程安全的时,我们什么时候使用 compareAndSet?

举例来说,我想自动设置一个变量,这样每个其他线程都可以看到它(但我希望以线程安全的方式设置变量)我可以简单地将它声明为 volatile AtomicBoolean 或 volatile AtomicInteger 并且应该好吗?我在哪些情况下需要使用 compareAndSet?

最佳答案

多线程环境中有两个重要的概念。

  1. 原子性
  2. 知名度

Volatile 解决了可见性问题,但它不处理原子性,例如我++。这里 i++ 不是单个机器指令,而是三个机器指令。

  1. 复制值到注册
  2. 增加它
  3. 放回去

AtomicInteger, AtomicReference 是基于比较和交换指令。 CAS 有三个操作数,一个用于操作的内存位置 V,预期的旧值 A 和新值 B。CAS 以原子方式将 V 更新为新值 B,但前提是 V 中的值与预期的旧值 A 匹配;否则它什么都不做。在任何一种情况下,它都会返回当前在 V 中的值。JVM 在 AtomicIntegerAtomicReference 中使用它,并将该函数称为 compareAndSet() 如果底层处理器不支持此功能,则 JVM 通过自旋锁实现它。

设置是原子的(它并不总是正确的)但是比较然后设置不是原子的。因此,当您对此有要求时,例如当值是 X 然后只更改为 Y 所以要以原子方式执行此操作你需要这种原语 你可以使用 AtomicInteger 的 compareAndSet,AtomicReference 例如atomicLong.compareAndSet(长期望,长更新)

您实际上可以使用这些原语来开发强大的数据结构,例如并发堆栈。

import java.util.concurrent.atomic.AtomicReference;

public class MyConcurrentStack<T> {

private AtomicReference<Node> head = new AtomicReference<Node>();

public MyConcurrentStack() {
}

public void push(T t) {
if (t == null) {
return;
}
Node<T> n = new Node<T>(t);
Node<T> current;

do {
current = head.get();
n.setNext(current);
} while (!head.compareAndSet(current, n));
}

public T pop() {
Node<T> currentHead = null;
Node<T> futureHead = null;
do {
currentHead = head.get();
if (currentHead == null) {
return null;
}
futureHead = currentHead.next;
} while (!head.compareAndSet(currentHead, futureHead));

return currentHead.data;
}

/**
*
* @return null if no element present else return a element. it does not
* remove the element from the stack.
*/
public T peek() {
Node<T> n = head.get();
if (n == null) {
return null;
} else {
return n.data;
}
}

public boolean isEmpty() {
if (head.get() == null) {
return true;
}
return false;
}

private static class Node<T> {

private final T data;
private Node<T> next;

private Node(T data) {
this.data = data;
}

private void setNext(Node next) {
this.next = next;
}
}
}

关于java - 当 set 在 Java 中已经是原子的时,为什么我们需要 compareAndSet?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37716360/

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