我了解 ABA 问题。但我无法理解的是:他们说在自动垃圾收集的语言中可能无法展示。所以我的问题是:
答案 0 :(得分:8)
当启用自动垃圾收集时,不能同时使用相同的引用分配两个对象并且共存,这是因为只要引用计数大于0,引用本身就不会被释放并重新使用。
因此,当某人仍有旧参考时,您无法将参考内容“切换”为不同对象的“点”。
答案 1 :(得分:2)
ABA问题与垃圾收集正交。例如,应用程序可以将对象从链表移动到空闲列表,然后立即重新使用它们。因此,在重新使用之前,对象永远不会被释放。 话虽如此,ABA问题可能以这种方式发生:
Thread1:
prevHead = head;
Thread2:
prevHead = head;
newHead = getFromFreeList();
if (cas(&head, prevHead, newHead)) addToFreeList(prevHead);
Thread3:
prevHead = head;
newHead = getFromFreeList(); // Get the same object 'released' by Thread2
cas(&head, prevHead, newHead) // succeeds and put back what was removed by Thread2
Thread1:
newHead = getFromFreeList();
if (cas(&head, prevHead, newHead)) addToFreeList(prevHead);
// CAS will succeed although it shouldn't since there were
// a modification on the head done by 'Thread3' in between.
答案 2 :(得分:1)
自动垃圾收集如何防止发生ABA问题? 请参阅Herlihy Shavit的“多处理器编程的艺术”。引用:它(ABA问题)经常出现,尤其是动态内存算法。
所以当然ABA问题可以出现在Java中,但是由于在大多数情况下问题出现在动态内存算法中并且你没有经常在java中实现这样的算法,所以你不会在java中看到这个错误常。
是否可以在java中使用,如果可以,怎么做? 书“多处理器编程的艺术”在java中给出了一个与无锁并发队列的内存回收相关的问题的例子。
是否可以防止这种情况发生?引用:通过测试避免ABA,两个时间点的值不相同,但这些值之间的值是否有所变化点。一种方法是使用AtomicStampedReference
答案 3 :(得分:1)
在“多处理器编程的艺术”一书中,作者讨论了程序员可能希望在Java中实现自己的资源池(例如,列表节点池)的情况。然后,直接管理池的程序员绕过垃圾收集,从而提高性能。尽管如此,必须谨慎避免ABA问题。
以下是Java中用于内存管理的Java代码的核心:
scale-down
LockFreeQueueRecycle.java的完整代码可在此处获取:
http://booksite.elsevier.com/9780123705914/exercises/07~Chapter_10.zip
请参阅第10章的幻灯片和代码:
http://booksite.elsevier.com/9780123705914/?ISBN=9780123705914