锁定免费的CAS混淆

时间:2011-05-13 12:12:05

标签: java multicore cas lock-free

嘿伙计们,
我正在阅读这些所谓的非阻塞技术,但我几乎没有怀疑:

1)使用原子操作执行无锁操作,现在这些原子操作是什么?我的意思是在一定程度上他们还需要锁定吗?那么这种无锁方法是否只能让我们以更精细的粒度锁定?
2)他们说非阻塞列表,现在应该是一个非阻塞列表:如果同一个插入的多个线程出现,只有一个会成功,另一个会做其他工作吗?,但是如果除了插入一个节点之外,其他线程别无选择,那么它是如何进行非阻塞的呢?它不会被阻止,直到前一个完成?
3)在java中,它们如何进行原子操作?他们不会像 synchronized boolean ..... 那样做 那么它是如何锁定的,因为它们正在获取锁定即同步部分? 4)CAS通常用于实现原子操作。那么cas不允许在同一个对象上只发生一个操作,并且停止(阻止)那些想要对同一个对象进行操作的人吗? 很抱歉这么多疑惑...... 请澄清......

修改 当我有一个要更新的结构时会发生什么?它是否也受硬件支持?不对,那么语言是否会在某种程度上获取锁定以使这些结构操作成为原子? 关于 JAVA :有AtomicReference和AtomicReferenceFieldUpdater类,它为对象(结构或任何类型的对象)提供更新,所以我们可以在性能方面比较它们,我的意思是速度吗?在tern中都使用了使用Native类的Unsafe类。

2 个答案:

答案 0 :(得分:5)

这是AtomicInteger中的一个简单的无锁方法

public final int getAndIncrement() {
    for (;;) {
        int current = get();
        int next = current + 1;
        if (compareAndSet(current, next))
            return current;
    }
}

您可以看到它获取值,递增它并执行compareAndSwap。如果compareAndSwap找不到期望值,则表示另一个线程已更改该值。所以它再次尝试,直到尝试更改值的所有其他线程都这样做。这是免锁的,因为没有锁使用,但没有阻塞,因为它可能不得不再次尝试(这是罕见的)不止一次(非常罕见)


  

1)使用原子操作执行无锁操作,现在这些原子操作是什么?我的意思是在一定程度上他们还需要锁定吗?那么这种无锁方法是否只能让我们以更精细的粒度锁定?

但是,使用更原始的操作来实现锁定。否则你需要一个锁来实现锁定adnauseum。无锁方法使用原子操作,避免完全锁定。

  2)他们说非阻塞列表,现在应该是一个非阻塞列表:如果同一个插入有多个线程,只有一个会成功,另一个会做其他工作吗? ,

如果它的线程安全,它们都应该成功,一次一个。

  

但是如果除了插入节点之外其他线程别无选择那么它是如何进行非阻塞的呢?

该术语是“并发”。它仍然需要等待另一个线程完成,它使用无锁方法来执行此操作。

  

在上一个完成之前不会被阻止吗?

  3)在java中,它们如何进行原子操作?

有一个调用本机方法来执行原子操作。您可以通过阅读代码来看到这一点。 ;)从查看生成的本机代码,这些本机方法转换为性能的机器代码指令(而不是真正的方法调用)

  

他们不会做像synchronized boolean .....这样它是如何锁定的,因为它们正在获取锁定即同步部分?

不,如果您阅读了代码,您会发现它没有。

  

4)CAS通常用于实现原子操作。所以cas不允许在同一个对象上发生一次操作,

没有

  

并停止(阻止)那些想要在同一个对象上操作的人?

没有

同样,如果你看一下如何使用它可能会更有意义。

答案 1 :(得分:2)

  

1)使用原子操作执行无锁操作,现在这些原子操作是什么?

E.g。递增计数器包括

  1. 读取当前值,
  2. 递增内存中的值,
  3. 回写更新后的值。
  4. 原子性意味着这些都发生在一个单一的,不可挽回的变化中。

      

    我的意思是在一定程度上他们还需要锁定吗?

    错误。 CAS背后的基本思想是执行上面的前两个步骤,然后在第三个步骤之前,它们检查值是否在两者之间发生了变化,如果是,则失败。然后可以稍后使用新值重试更改。

    没有涉及经典锁定,因为3个步骤中的每个步骤本身都是原子的。现代处理器支持第3(比较和交换)操作,因此可能说它涉及到寄存器级别的某种锁定(坦率地说,我不知道它是如何实现的)但是无论如何,这与Java中锁定通常意味着的不一样。

    CAS的好处是提高了性能,因为即使在当前JVM中提高了锁定性能,CAS仍然更便宜,特别是在争用的情况下(即,当多个线程在操作时发生碰撞时)。在这种情况下,使用锁定,一个或多个线程被挂起,而新线程被置于上下文中,即使它不涉及交换内存,这也是一项非常昂贵的操作。

      

    2)他们说非阻塞列表,现在应该是一个非阻塞列表

    在这里,您可能会混淆两个不同的术语。非阻塞列表是不阻塞插入/删除的列表,这通常意味着其大小不受限制(例如CopyOnWriteArrayList)。将其与例如一个阻塞队列(例如ArrayBlockingQueue),它具有固定的最大大小,并且在达到其大小限制时,其他插入调用将被阻止,直到有更多空间可用(在其他一些线程从队列中删除元素之后)。

    使用无锁算法(例如ConcurrentHashMap)实现线程安全的集合与非阻塞集合不同。