Richard Richard - 3 months ago 20
Java Question

thread-safe of ImprovedList from Java Concurrency in Practice

I read Java Concurrency in Practice. It says this class is thread safe:

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(); }
}


I don't think so. The constructor argument
list
can be referenced in another thread. So if this
list
is not thread safe, it can be inconsistent in concurrency. if this
list
is thread safe, another thread operates it with the lock of
list
, and the thread using ImprovedList operates it with the lock of
ImprovedList
object lock, so they can still mutate it concurrently.

Who can tell me where I am wrong?

Answer

A citation from the book:

this is guaranteed to provide thread safety so long as our class holds the only outstanding reference to the underlying List.

So, you're right that the class cannot be called thread-safe if someone holds a reference to the same list. But you're wrong in not reading the book attentively.

Comments