Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用Java AtomicStampedReference的算法可以被认为是非阻塞的吗?_Java_Multithreading_Algorithm_Data Structures_Concurrency - Fatal编程技术网

使用Java AtomicStampedReference的算法可以被认为是非阻塞的吗?

使用Java AtomicStampedReference的算法可以被认为是非阻塞的吗?,java,multithreading,algorithm,data-structures,concurrency,Java,Multithreading,Algorithm,Data Structures,Concurrency,我正试图实现非阻塞二叉搜索树,如使用Java所述。该算法基于单世界CAS,但: 国家和信息 字段一起存储在CAS对象中。因此,内部 节点使用四个字的内存 我决定使用原子StampedReference来存储这些数据。问题是它 通过创建表示“盒装”[reference,integer]对的内部对象来维护戳记引用 该结构的内部实施: public boolean compareAndSet(V expectedReference, V

我正试图实现非阻塞二叉搜索树,如使用Java所述。该算法基于单世界CAS,但:

国家和信息 字段一起存储在CAS对象中。因此,内部 节点使用四个字的内存

我决定使用原子StampedReference来存储这些数据。问题是它

通过创建表示“盒装”[reference,integer]对的内部对象来维护戳记引用

该结构的内部实施:

public boolean compareAndSet(V   expectedReference,
                             V   newReference,
                             int expectedStamp,
                             int newStamp) {
    Pair<V> current = pair;
    return
        expectedReference == current.reference &&
        expectedStamp == current.stamp &&
        ((newReference == current.reference &&
          newStamp == current.stamp) ||
         casPair(current, Pair.of(newReference, newStamp)));
}
公共布尔比较数据集(V expectedReference,
五、新参考,
int expectedStamp,
int新闻坦普){
对电流=对;
返回
expectedReference==current.reference&&
expectedStamp==current.stamp&&
((newReference==current.reference)&&
newStamp==当前的.stamp)||
casPair(当前,成对(newReference,newStamp));
}
对定义为:

private static class Pair<T> {
    final T reference;
    final int stamp;
    private Pair(T reference, int stamp) {
        this.reference = reference;
        this.stamp = stamp;
    }
    static <T> Pair<T> of(T reference, int stamp) {
        return new Pair<T>(reference, stamp);
    }
}
私有静态类对{
最终T参考;
最后印花;
专用对(T参考,整数戳记){
this.reference=参考;
这个.邮票=邮票;
}
静态对(T参考,int戳记){
返回新的一对(参考、盖章);
}
}
这个实现仍然是非阻塞的吗

还有一个额外的问题:是什么使这个比较数据集操作原子化?

我们称之为无锁算法是什么? [免责声明]在我明确写这篇文章之前,我的发言是关于一般的算法,而不是考虑Java CAS实现

是的,我认为基于CAS的算法可以被认为是无锁的。提供无锁算法的定义:

在计算机科学中,非阻塞算法可确保竞争共享资源的线程不会因互斥而无限期推迟执行。无阻塞算法是无锁的
,前提是无论调度如何,都能保证系统范围内的进度

因此,在现代用法中,如果一个或多个线程的暂停不会阻止其余线程的潜在进程,则算法是非阻塞的

让我们在该上下文中看一看基于CAS的算法[称为算法,我的意思是使用CAS指令和while循环设置变量]:

问题一:基于CAS的算法是非阻塞的吗?在每个特定时刻,都有一个线程将成功地执行CAS变量。如果我们暂停其中一个,剩下的一个就会成功。因此,算法满足我引用的定义,答案是肯定的

问题二:基于CAS的算法是无锁的吗?我想答案也是肯定的,因为保证了系统范围内的,但不是每个线程的进度(每个线程最终都会成功捕获变量)

<强>现在,考虑java中使用的基于CAS的算法,使用< AtomicXXX > <代码>类及其对象上的CAS操作。<强>技术上,由于JVM方面可能的外部影响,不能保证算法的无锁性:

public class Entity {
    static {
        new Thread(){
            @Override
            public void run() {
                synchronized (getClass().getClassLoader()){
                    try {
                        getClass().getClassLoader().wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }.start();
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        AtomicReference v = new AtomicReference(new Object());
        Object var = null;
        Object somenew;
        do {
            var = v.get();
            somenew = new Object();
        } while(!v.compareAndSet(var, somenew));
    }

}
main()
中实现的算法是无锁的,但由于类加载器的监视器从未收到通知,因此系统范围内不会有任何进展那么,我刚才到底写了什么?说基于cas的算法在Java中是无锁的,只是因为它们是基于cas的,这是错误的

指令原子性 CAS指令的定义是原子的在大多数现代CPU中支持此指令,即执行我们期望它执行的操作,并以原子方式执行。比如说,CPU供应商保证CPU支持原子CA

引述:

自1970年以来,Compare and Swap(以及Compare and Swap Double)一直是IBM370(以及所有后续)体系结构的一个组成部分

截至2013年,大多数多处理器体系结构在硬件上支持CAS

JDK的一些证明:

AtomicInteger.compareAndSet()
表示:

原子地如果当前值==预期值,则将该值设置为给定的更新值

同样可以在
AtomicXXX
类中找到,您可以很容易地找到它,所以不值得在这里复制粘贴

现在,让我们考虑<代码> AtomicStampedReference .CabaseDeSET()/<代码>。它说:

如果当前引用==预期引用且当前戳记等于预期戳记,则原子地将引用和戳记的值设置为给定的更新值


我认为从那个javadoc我们不能得出结论,整个操作是原子的,它只是原子地设置值,所以要么设置了stamp和reference,要么在CAS失败时不设置它们。

您主要是询问Java代码的特定语义,所以这个问题更适合于堆栈溢出。但你可能需要澄清一些事情才能在某个时候得到一个好的答案。(1) 什么是
casPair()
?(2) 您在顶部说您正在使用
AtomicStampedReference
,但在代码中的任何地方都不要提及它,(3)不清楚为什么您在第二个引号之前使用“problem”一词,为什么AtomicStampedReference在原子上维护一个装箱对会有问题?这里可能有一个关于数据结构的问题,但是这个问题是关于Java库的行为,所以它完全是一个编程问题,而不是一个计算机科学问题。因此,我将这个问题迁移到了。问题二:但是调用方法compareAndSet()也被建议是原子的,因为它包含多个操作。@atok