gpt4 book ai didi

java - 使用 CAS 代替同步

转载 作者:行者123 更新时间:2023-11-30 07:01:38 24 4
gpt4 key购买 nike

最近,我在创建一个生产可重用实例的工厂时遇到了一种情况。

public class Factory {
private static final int REUSABLE_TIMES_LIMIT = 10;
private static Product instance = new Product();
private static int getTimes;

public static synchronized Product getInstance() {
if (++getTimes >= REUSABLE_TIMES_LIMIT) {
return nextInstance();
}
return instance;
}

public static synchronized Product nextInstance() {
getTimes = 0;
instance = new Product();
return instance;
}
}

getInstance()nextInstance()在我的情况下,可能会被不同的线程同时调用,我选择添加 synchronized每个词前面都有关键词。然而,synchronized当很多线程进入该方法时,它太重了,所以我想基于 CAS 重写这个类,即 java.util.concurrent.atomic 包中的那些类。不幸的是,我没有找到一个正确的方法来安排我的代码与两个原子变量,即 instancegetTimes , 在同一时间。有人会告诉我如何正确使用 CAS而不是synchronized在这种情况下不会引起竞争条件?预先感谢:)

最佳答案

一种可能的选择是使用一个 AtomicReference 而不是两个。无论代码复杂程度如何,这都会使您的状态保持一致。

public static class ProductStorage {
private Product product;
private int getTimes;

public ProductStorage(Product product, int getTimes) {
this.product = product;
this.getTimes = getTimes;
}
}

public static class Factory {
private static final int REUSABLE_TIMES_LIMIT = 10;
private static AtomicReference<ProductStorage> instance = new AtomicReference<>(
new ProductStorage(new Product(), 0)
);

public static Product getInstance() {
ProductStorage current;
for(;;) {
current = instance.get();
if(current.getTimes >= REUSABLE_TIMES_LIMIT) {

instance.compareAndSet(current, new ProductStorage(new Product(), 0));
continue;
}
if(current.getTimes < REUSABLE_TIMES_LIMIT) {

if(instance.compareAndSet(current, new ProductStorage(current.product, current.getTimes + 1))) {
return current.product;
}
}
}
}
}

您可能提到的第一件事是,在这种情况下总是会分配新对象。但请记住,大多数无锁算法都会这样做,这不是问题。 java 中的分配速度很快并且花费几纳秒。您也可能在 Martin Thompson's blog 中看到类似的解决方案。代码是here 。在我的机器上,无锁解决方案的运行速度快了 3-4 倍。

如果可能想要使用两个原子,但这将使 getTimes 的计数变得困难。

关于java - 使用 CAS 代替同步,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40811070/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com