Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/332.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并发性改进列表的线程安全性_Java_Concurrency - Fatal编程技术网

Java并发性改进列表的线程安全性

Java并发性改进列表的线程安全性,java,concurrency,Java,Concurrency,我在实践中阅读了Java并发。它说这个类是线程安全的: package net.jcip.examples; import java.util.*; import net.jcip.annotations.*; /** * ImprovedList * * Implementing put-if-absent using composition * * @author Brian Goetz and Tim Peierls */ @ThreadSafe public class

我在实践中阅读了Java并发。它说这个类是线程安全的:

package net.jcip.examples;

import java.util.*;

import net.jcip.annotations.*;

/**
 * ImprovedList
 *
 * Implementing put-if-absent using composition
 *
 * @author Brian Goetz and Tim Peierls
 */
@ThreadSafe
public class ImprovedList<T> implements List<T> {
    private final List<T> list;

    public ImprovedList(List<T> list) { this.list = list; }

    public synchronized boolean putIfAbsent(T x) {
        boolean contains = list.contains(x);
        if (contains)
            list.add(x);
        return !contains;
    }

    // Plain vanilla delegation for List methods.
    // Mutative methods must be synchronized to ensure atomicity of putIfAbsent.

    public int size() {
        return list.size();
    }

    public boolean isEmpty() {
        return list.isEmpty();
    }

    public boolean contains(Object o) {
        return list.contains(o);
    }

    public Iterator<T> iterator() {
        return list.iterator();
    }

    public Object[] toArray() {
        return list.toArray();
    }

    public <T> T[] toArray(T[] a) {
        return list.toArray(a);
    }

    public synchronized boolean add(T e) {
        return list.add(e);
    }

    public synchronized boolean remove(Object o) {
        return list.remove(o);
    }

    public boolean containsAll(Collection<?> c) {
        return list.containsAll(c);
    }

    public synchronized boolean addAll(Collection<? extends T> c) {
        return list.addAll(c);
    }

    public synchronized boolean addAll(int index, Collection<? extends T> c) {
        return list.addAll(index, c);
    }

    public synchronized boolean removeAll(Collection<?> c) {
        return list.removeAll(c);
    }

    public synchronized boolean retainAll(Collection<?> c) {
        return list.retainAll(c);
    }

    public boolean equals(Object o) {
        return list.equals(o);
    }

    public int hashCode() {
        return list.hashCode();
    }

    public T get(int index) {
        return list.get(index);
    }

    public T set(int index, T element) {
        return list.set(index, element);
    }

    public void add(int index, T element) {
        list.add(index, element);
    }

    public T remove(int index) {
        return list.remove(index);
    }

    public int indexOf(Object o) {
        return list.indexOf(o);
    }

    public int lastIndexOf(Object o) {
        return list.lastIndexOf(o);
    }

    public ListIterator<T> listIterator() {
        return list.listIterator();
    }

    public ListIterator<T> listIterator(int index) {
        return list.listIterator(index);
    }

    public List<T> subList(int fromIndex, int toIndex) {
        return list.subList(fromIndex, toIndex);
    }

    public synchronized void clear() { list.clear(); }
}
我不这么认为。构造函数参数列表可以在另一个线程中引用。因此,如果这个列表不是线程安全的,那么它在并发性方面可能不一致。如果此列表是线程安全的,则另一个线程使用列表锁对其进行操作,而使用ImprovedList的线程使用ImprovedList对象锁对其进行操作,因此它们仍然可以同时对其进行变异


谁能告诉我哪里错了?你是对的。如果您想使这样的列表真正线程安全,那么传入列表只是直接使用而不是复制的事实(例如)允许在任何其他对象的上下文中进行更改,该对象包含对该初始传入列表的引用

除此之外;这种实现甚至允许对不同步的列表进行硬修改;像

public T remove(int index) {

所以-我同意你的评估;这看起来并不完全是线程安全的。在某种程度上是这样;但是,作为90%的线程安全性,这就相当于一个90%完成的项目,对吗

你说得对。如果您想使这样的列表真正线程安全,那么传入列表只是直接使用而不是复制的事实(例如)允许在任何其他对象的上下文中进行更改,该对象包含对该初始传入列表的引用

除此之外;这种实现甚至允许对不同步的列表进行硬修改;像

public T remove(int index) {

所以-我同意你的评估;这看起来并不完全是线程安全的。在某种程度上是这样;但是,作为90%的线程安全性,这就相当于一个90%完成的项目,对吗

这本书的引文:

这是保证提供线程安全,只要我们的类 保存对基础列表的唯一未完成引用


因此,如果有人持有对同一列表的引用,那么该类就不能称为线程安全的,这是对的。但是你没有认真阅读这本书是错误的。

这本书的引文:

这是保证提供线程安全,只要我们的类 保存对基础列表的唯一未完成引用


因此,如果有人持有对同一列表的引用,那么该类就不能称为线程安全的,这是对的。但是你没有认真阅读这本书是错误的。

你错过了一个要点:

ImprovedList假设一旦列表被传递给其构造函数,客户端将不再直接使用基础列表,而只通过ImprovedList访问它

因此,您的加薪不适用于此用例。ImprovedList与Collections.synchronizedListList类似,它只是一个包装类,可以防止使用内在锁对基础列表进行任何并发修改。如果提供给构造函数的列表不是直接访问的,而是通过ImprovedList访问的,它是线程安全的,这是您在本例中应该理解的


但实际上,一般来说,如果您共享提供给构造函数的非线程安全列表,并且在知道创建非线程安全列表的安全副本不是线程安全操作之后,您没有首先创建它的安全副本,那么它就不再是线程安全的了。但是请注意,共享非线程安全列表是一个错误,因此它不是一个真正的实际使用案例。

您忽略了一个要点:

ImprovedList假设一旦列表被传递给其构造函数,客户端将不再直接使用基础列表,而只通过ImprovedList访问它

因此,您的加薪不适用于此用例。ImprovedList与Collections.synchronizedListList类似,它只是一个包装类,可以防止使用内在锁对基础列表进行任何并发修改。如果提供给构造函数的列表不是直接访问的,而是通过ImprovedList访问的,它是线程安全的,这是您在本例中应该理解的


但实际上,一般来说,如果您共享提供给构造函数的非线程安全列表,并且在知道创建非线程安全列表的安全副本不是线程安全操作之后,您没有首先创建它的安全副本,那么它就不再是线程安全的了。但是,请注意,共享非线程安全列表是一个错误,因此它并不是一个真实的用例。

谢谢,@GhostCat。我不知道为什么没有人告诉作者纠正它或只是澄清前提条件。太令人困惑了。试着给他们发邮件/推特。。。或许,我们都错了;忽视一些事情;所以你可以要求那些人澄清-好啊我将邀请作者回答这个问题并指出我可能的错误。为了为这本书的作者辩护,可能是Java世界最著名的并发专家:1书中的引文:这保证提供线程安全性这么长时间
因为我们的类持有对基础列表的唯一突出引用;2非同步删除方法不是书中的,是@Richard添加的。对。考虑到他们是真正的专家,我也想到了我错过的东西。代码来自他们的网站谢谢,@GhostCat。我不知道为什么没有人告诉作者纠正它或只是澄清前提条件。太令人困惑了。试着给他们发邮件/推特。。。或许,我们都错了;忽视一些事情;所以你可以要求那些人澄清-好啊我将邀请作者回答这个问题,并指出我可能的错误。为这本书的作者辩护,这本书可能是Java世界最著名的并发专家:1书中的引文:只要我们的类持有对底层列表的唯一杰出引用,这保证提供线程安全;2非同步删除方法不是书中的,是@Richard添加的。对。考虑到他们是真正的专家,我也想到了我错过的东西。代码来自他们的网站我想你在列表之前遗漏了一点文字:像Collections.synchronizedList和其他Collections包装器一样,ImprovedList假设一旦一个列表被传递给它的构造函数,客户端就不会再直接使用底层列表,仅通过ImprovedList访问它。我认为您缺少列表之前的一段文字:与Collections.synchronizedList和其他集合包装器一样,ImprovedList假设一旦将列表传递给其构造函数,客户端将不再直接使用基础列表,仅通过ImprovedList访问它。这本书提到了ImprovedList,额外的同步层的性能损失很小,因为对底层的访问总是没有争议的。参见包含改进列表列表的同一页底部的脚注7,内容为:[7]由于基础列表上的同步保证是无争用的,因此速度很快,因此惩罚很小;见第11章。我的问题是,如果多个线程同时访问ImprovedList怎么办?那怎么可能是无可辩驳的呢?我误解了什么?谢谢。书中提到了ImprovedList,因为对底层的访问总是毫无争议的,所以额外的同步层的性能损失很小。参见包含改进列表列表的同一页底部的脚注7,内容为:[7]由于基础列表上的同步保证是无争用的,因此速度很快,因此惩罚很小;见第11章。我的问题是,如果多个线程同时访问ImprovedList怎么办?那怎么可能是无可辩驳的呢?我误解了什么?谢谢