问题 ABA在无锁算法中


我明白了 ABA 问题。但我无法理解的是:他们用语言说 自动垃圾收集 它可能不会展出。所以我的问题是:

  • 自动垃圾收集如何防止ABA问题发生?
  • 是否有可能在java中,如果可以,如何?
  • 有可能防止这种情况发生吗?

6351
2017-10-29 14:15


起源



答案:


  • 当启用自动垃圾收集时,不能同时使用相同的引用分配两个对象并共存,这是因为只要引用计数大于0,引用本身就不会被释放和重用。

    因此,当某人仍有旧参考时,您无法将参考内容“切换”为不同对象的“点”。


8
2017-10-29 16:27





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
2017-09-26 05:00





自动垃圾收集如何防止ABA问题发生? 请参阅Herlihy Shavit的“多处理器编程的艺术”。引用: 它(ABA问题)经常出现,特别是在动态记忆算法中

因此,当然ABA问题可以出现在Java中,但由于在大多数情况下问题出现在动态内存算法中,并且您不经常在java中实现此类算法,因此您不会经常在java中看到此错误。

是否有可能在java中,如果可以,如何?  书“多处理器编程的艺术”在java中给出了一个与无锁并发队列的内存回收相关的问题的例子。

有可能防止这种情况发生吗? 引用: 通过测试避免ABA,两个时间点的值不相同,但这些值之间的值是否发生了变化。 一种方法是使用AtomicStampedReference


1
2017-10-30 19:19



请在这里给出书中的着作,以便每个人都可以关注。你可以把这个网址作为参考。 - Trying
这可能会有所帮助 cs.brown.edu/courses/cs176 - arunmoezhi
@Thomas Krieger这不是礼貌的回答 - “读书” - gstackoverflow
@gstackoverflow,不仅是“读过这本书”的礼貌,它还是一个非常强大而慷慨的答案。它为您提供了发展自己力量的方法。多么令人遗憾的是,你无法欣赏并表现出这种忘恩负义。现在我明白你是否读过这本书并不好,但即便如此,人们也必须欣赏这种精神,不仅提供简短的意见,而且提供深入,权威的对待。请阅读并学习并表示尊重。 - Lew Bloch
@Lew Bloch,如果我没有这本书,我还有其他方法可以得到回应吗?如果人理解书正确 - 它可以解释在这个vook解释的主题 - gstackoverflow


答案:


  • 当启用自动垃圾收集时,不能同时使用相同的引用分配两个对象并共存,这是因为只要引用计数大于0,引用本身就不会被释放和重用。

    因此,当某人仍有旧参考时,您无法将参考内容“切换”为不同对象的“点”。


8
2017-10-29 16:27





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
2017-09-26 05:00





自动垃圾收集如何防止ABA问题发生? 请参阅Herlihy Shavit的“多处理器编程的艺术”。引用: 它(ABA问题)经常出现,特别是在动态记忆算法中

因此,当然ABA问题可以出现在Java中,但由于在大多数情况下问题出现在动态内存算法中,并且您不经常在java中实现此类算法,因此您不会经常在java中看到此错误。

是否有可能在java中,如果可以,如何?  书“多处理器编程的艺术”在java中给出了一个与无锁并发队列的内存回收相关的问题的例子。

有可能防止这种情况发生吗? 引用: 通过测试避免ABA,两个时间点的值不相同,但这些值之间的值是否发生了变化。 一种方法是使用AtomicStampedReference


1
2017-10-30 19:19



请在这里给出书中的着作,以便每个人都可以关注。你可以把这个网址作为参考。 - Trying
这可能会有所帮助 cs.brown.edu/courses/cs176 - arunmoezhi
@Thomas Krieger这不是礼貌的回答 - “读书” - gstackoverflow
@gstackoverflow,不仅是“读过这本书”的礼貌,它还是一个非常强大而慷慨的答案。它为您提供了发展自己力量的方法。多么令人遗憾的是,你无法欣赏并表现出这种忘恩负义。现在我明白你是否读过这本书并不好,但即便如此,人们也必须欣赏这种精神,不仅提供简短的意见,而且提供深入,权威的对待。请阅读并学习并表示尊重。 - Lew Bloch
@Lew Bloch,如果我没有这本书,我还有其他方法可以得到回应吗?如果人理解书正确 - 它可以解释在这个vook解释的主题 - gstackoverflow


在“多处理器编程的艺术”一书中,作者讨论了程序员可能希望在Java中实现他们自己的资源池(例如,列表节点池)的情况。然后,直接管理池的程序员绕过垃圾收集,从而提高性能。尽管如此,必须谨慎避免ABA问题。

以下是Java中用于内存管理的Java代码的核心:

ThreadLocal<Node> freeList = new ThreadLocal<Node>() {
    protected Node initialValue() { return null; };
};

LockFreeQueueRecycle.java的完整代码可在此处获得:

http://booksite.elsevier.com/9780123705914/exercises/07~Chapter_10.zip

请参阅第10章的幻灯片和代码:

http://booksite.elsevier.com/9780123705914/?ISBN=9780123705914


1
2018-06-18 20:02