可以创建可以原子交换的 AtomicReference 吗?
有没有办法实现一种引用类型,其值可以与另一种原子交换?
在 Java 中,我们有 AtomicReference
,它可以与局部变量交换,但不能与另一个 AtomicReference
交换。
您可以执行以下操作:
AtomicReference r1 = new AtomicReference("hello");
AtomicReference r2 = new AtomicReference("world");
并通过两个操作的组合来交换它们:
r1.set(r2.getAndSet(r1.get()));
但这会使它们之间处于不一致的状态,其中都包含 "hello"
。此外,即使您可以原子地交换它们,您仍然无法原子地读取它们(作为一对)。
我希望能够做的是:
PairableAtomicReference r1 = new PairableAtomicReference("hello");
PairableAtomicReference r2 = new PairableAtomicReference("world");
AtomicRefPair rp = new AtomicRefPair(r1, r2);
然后
Object[] oldVal, newVal;
do {
oldVal = rp.get();
newVal = new Object[] {oldVal[1], oldVal[0]};
} while (! rp.compareAndSet(oldVal, newVal));
交换值,并在另一个线程中:
AtomicRefPair otherRP = new AtomicRefPair(r1, r2);
System.out.println(Arrays.toString(otherRP.get()));
并确保输出为 [hello, world]
或 [world,你好]
。
注意:
r1
和r2
在此操作中配对,但另一个线程可能会独立配对,例如r1
和另一个r3
(不幸的是,这意味着我无法使用 这个解决方案。)- 将会有数十万个这样的引用,因此全局
ReentrantLock
将是一个主要瓶颈。 rp
和otherRP
不一定在线程之间共享,因此简单地锁定它们是行不通的。它们可以实习,但实习生池需要自己的同步,这将是另一个瓶颈。- 我在这里只制作了 2 个参考文献的分组,但是能够将 3 个或更多的参考文献分组将是一个额外的好处。
是否可以实现 AtomicRefPair
的无锁版本?我有预感,但如果不是,那么也许有一篇文章解释了原因?
Is there any way to implement a type of reference whose value can be exchanged with another atomically?
In Java we have AtomicReference
which can be swapped with a local variable but not with another AtomicReference
.
You can do:
AtomicReference r1 = new AtomicReference("hello");
AtomicReference r2 = new AtomicReference("world");
and swap them with a combination of two operations:
r1.set(r2.getAndSet(r1.get()));
But this leaves them in an inconsistent state in between, where both contain "hello"
. Also even if you could swap them atomically, you still could not read them (as a pair) atomically.
What I would like to be able to do is:
PairableAtomicReference r1 = new PairableAtomicReference("hello");
PairableAtomicReference r2 = new PairableAtomicReference("world");
AtomicRefPair rp = new AtomicRefPair(r1, r2);
then
Object[] oldVal, newVal;
do {
oldVal = rp.get();
newVal = new Object[] {oldVal[1], oldVal[0]};
} while (! rp.compareAndSet(oldVal, newVal));
to swap the values, and in another thread:
AtomicRefPair otherRP = new AtomicRefPair(r1, r2);
System.out.println(Arrays.toString(otherRP.get()));
and be certain that the output will be either [hello, world]
or [world, hello]
.
Notes:
r1
andr2
are paired for this operation, but it's possible that another thread will independently pair, sayr1
and anotherr3
(unfortunately that means I cannot use this solution.)- There will be hundreds of thousands of these references, so a global
ReentrantLock
would be a major bottleneck. rp
andotherRP
are not necessarily shared between threads, so simply locking them will not work. They could be interned, but the intern pool would need its own synchronization which would be another bottleneck.- I have only made groups of 2 references here, but the ability to group 3 or more would be a bonus.
Is it possible to implement a lock-free version of AtomicRefPair
? I have a hunch that it isn't, but if not then maybe there is an article somewhere that explains why?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
有一个不可变的类来保存该对。那是你的原子。交换对意味着替换原子。
更新:你的问题不是很清楚。但一般来说,对于由多个变量组成的并发系统,人们可能需要
,如果它不消耗太多资源,您可以直接在快照中对系统进行建模。
Have an immutable class holding the pair. That is your atom. Swapping the pair means replacing the atom.
update: your question isn't very clear. but in general, for a concurrent system consisting of multiple variables, one might want
you can model your system directly in snapshots, if it doesn't consume too much resources.
我不知道是否有一个好的解决方案,但以下丑陋的解决方案可以工作:
I don't know if there's a nice solution, but the following ugly one could work: