Java 不安全的比较与同步

Java 不安全的比较与同步,java,concurrency,java.util.concurrent,unsafe,Java,Concurrency,Java.util.concurrent,Unsafe,我发现,几乎所有高级同步抽象,如信号量、CountDownLatch、java.util.concurrent和concurrent集合中的交换器,都使用unsalike compareAndSwapInt方法中的方法来定义关键部分。同时,我希望同步块或方法将用于此目的。 你能解释一下不安全的方法吗?我的意思是,只有那些方法可以在原子上设置一个比同步更有效的值,以及为什么会这样吗?如果你希望等待很长时间,例如毫秒,因为线程可以进入睡眠状态并释放CPU来做其他工作,那么使用同步的方法会更有效 如果

我发现,几乎所有高级同步抽象,如信号量、CountDownLatch、java.util.concurrent和concurrent集合中的交换器,都使用unsalike compareAndSwapInt方法中的方法来定义关键部分。同时,我希望同步块或方法将用于此目的。 你能解释一下不安全的方法吗?我的意思是,只有那些方法可以在原子上设置一个比同步更有效的值,以及为什么会这样吗?

如果你希望等待很长时间,例如毫秒,因为线程可以进入睡眠状态并释放CPU来做其他工作,那么使用同步的方法会更有效

如果您希望操作快速进行,则使用compareAndSwap会更高效。这是因为它是一条简单的机器代码指令,只需10纳秒。但是,如果资源满足度很高,则该指令必须忙着等待,如果它无法获得所需的值,则它可能会一直忙着消耗CPU,直到它获得所需的值为止

如果使用堆外内存,可以控制共享数据的布局,避免错误共享,因为同一缓存线由多个CPU更新。当您有多个可能要独立更新的值时,这一点很重要。e、 g.用于环形缓冲器

请注意,典型JVM的内部实现(例如hotspot)通常会使用比较和交换硬件指令作为同步实现的一部分,如果此类指令可用,例如,。x86,而另一种常见的替代方案是电源、ARM。一种典型的策略,用于快速路径,使用比较和交换或等效方法尝试获取锁(如果锁是空闲的),然后可能是短锁,如果失败,则返回到操作系统级阻塞原语,例如。细节远远超出了这一点,包括和等技术,这些技术最终取决于实现

如果希望等待很长时间(例如毫秒),则使用Synchronized会更有效,因为线程可能会进入休眠状态并释放CPU以执行其他工作

如果您希望操作快速进行,则使用compareAndSwap会更高效。这是因为它是一条简单的机器代码指令,只需10纳秒。但是,如果资源满足度很高,则该指令必须忙着等待,如果它无法获得所需的值,则它可能会一直忙着消耗CPU,直到它获得所需的值为止

如果使用堆外内存,可以控制共享数据的布局,避免错误共享,因为同一缓存线由多个CPU更新。当您有多个可能要独立更新的值时,这一点很重要。e、 g.用于环形缓冲器


请注意,典型JVM的内部实现(例如hotspot)通常会使用比较和交换硬件指令作为同步实现的一部分,如果此类指令可用,例如,。x86,而另一种常见的替代方案是电源、ARM。一种典型的策略,用于快速路径,使用比较和交换或等效方法尝试获取锁(如果锁是空闲的),然后可能是短锁,如果失败,则返回到操作系统级阻塞原语,例如。细节远远超出了这一点,包括和等技术,这些技术最终取决于实现

上述答案并不令人满意。方法是:互斥体同步是不必要的,因为只有一个操作完成了互斥体中所有的工作,而这只有一个操作不能中断。但这是一半的答案,因为在多核系统中,另一个CPU可以写入相同的内存位置。因此,compareAndSwap机器代码指令不仅在缓存中读写,而且还读写到实际内存中。这需要多一点访问RAM的时间。CompareAndSwap机器代码操作检查RAM内容是否与读取前的值相比发生了更改,然后才存储新值。如果我有更多的时间,我在这里写一个例子

有效,compareAndSwap访问比任何时候锁定和解锁都要快。但它只能在访问中只需更改一个确切的内存位置时使用。如果多个存储位置通常需要更改,并且始终保持一致,则不能使用compareAndSwap,只能使用Synchronized。在上面的答案中写道,compareAndSwap通常用于实现同步操作。这是正确的,因为在任务调度器中,单个同步的get mutex和end synchronized release mutex只需要一条原子指令。因此,原子访问是一切的基础。但是在同步的{…}之间,调度程序知道线程开关是受保护的

这种编程方法不仅适用于Java、C/++,可能还适用于其他语言——它也很重要,并且能够使用

Th 以上答案并不令人满意。方法是:互斥体同步是不必要的,因为只有一个操作完成了互斥体中所有的工作,而这只有一个操作不能中断。但这是一半的答案,因为在多核系统中,另一个CPU可以写入相同的内存位置。因此,compareAndSwap机器代码指令不仅在缓存中读写,而且还读写到实际内存中。这需要多一点访问RAM的时间。CompareAndSwap机器代码操作检查RAM内容是否与读取前的值相比发生了更改,然后才存储新值。如果我有更多的时间,我在这里写一个例子

有效,compareAndSwap访问比任何时候锁定和解锁都要快。但它只能在访问中只需更改一个确切的内存位置时使用。如果多个存储位置通常需要更改,并且始终保持一致,则不能使用compareAndSwap,只能使用Synchronized。在上面的答案中写道,compareAndSwap通常用于实现同步操作。这是正确的,因为在任务调度器中,单个同步的get mutex和end synchronized release mutex只需要一条原子指令。因此,原子访问是一切的基础。但是在同步的{…}之间,调度程序知道线程开关是受保护的


这种编程方法不仅适用于Java、C/++,可能还适用于其他语言——它也很重要,并且能够使用

你能详细说明最后一段吗?最后一段提到了哪个JVM?我对它进行了一些编辑,以便在另一个线程中的混淆上下文中澄清它。我认为关键是Peter在最后一段中指的是硬件CAS指令或类似指令,而不是导致混淆的任何Java语言级别的compareAndSwap方法或算法。您能详细说明最后一段吗?最后一段提到了哪个JVM?我对它进行了一些编辑,以便在另一个线程中的混淆上下文中澄清它。我认为关键是Peter在最后一段中指的是硬件CAS指令或类似指令,而不是导致混淆的任何Java语言级别的compareAndSwap方法或算法。