客户端加锁

对封装好的jar包来说,使用它的代码都是客户端。

客户端加锁是指,对于使用某个对象X的客户端代码,使用X本身用于保护其状态的锁来保护这段客户端代码。要使用客户端加锁,必须知道对象X使用的是哪一种锁。

public class ListHelper<E> {

    public List<E> list = Collections.synchronizedList(new ArrayList<>());

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

上边这段扩展Collections的客户端代码不是线性安全的,因为list和ListHelper使用了不同的内置锁,putIfAbsent相对于List的其他操作来说并不是原子的,因此无法保证当putIfAbsent执行时另一个线程不会修改链表。要使这个方法正确执行,必须使List和ListHelper使用同一把锁。在Collections的文档中指出,通过使用封装容器的内置锁来支持客户端加锁。

public  boolean putIfAbsent(E x) {
    synchronized(list) {
        boolean absent = !list.contains(x);
        if (absent) {
            list.add(x);
        }
        return absent;
    }
}
客户端加锁机制和扩展类机制有很多共同点,二者都是将派生类的行为与基类的实现耦合在一起,都会破坏实现的封装性。

当为现有的类增加一个原子操作时,使用组合是更好的选择。例如,通过实现List接口,新增功能putIfAbsent,这种方式比客户端加锁更健壮。事实上,组合使用了Java监视器模式来封装现有的List,并且只要在类中拥有指向底层的List的唯一外部引用,加上ImprovedList提供的一致的同步机制,就能保证线程安全性。

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

    @Override
    public int size() {
        return 0;
    }

    @Override
    public boolean isEmpty() {
        return false;
    }

    @Override
    public boolean contains(Object o) {
        return false;
    }

    @Override
    public Iterator<T> iterator() {
        return null;
    }

    @Override
    public Object[] toArray() {
        return new Object[0];
    }

    @Override
    public <T1> T1[] toArray(T1[] a) {
        return null;
    }

    @Override
    public boolean add(T t) {
        return false;
    }

    @Override
    public boolean remove(Object o) {
        return false;
    }

    @Override
    public boolean containsAll(Collection<?> c) {
        return false;
    }

    @Override
    public boolean addAll(Collection<? extends T> c) {
        return false;
    }

    @Override
    public boolean addAll(int index, Collection<? extends T> c) {
        return false;
    }

    @Override
    public boolean removeAll(Collection<?> c) {
        return false;
    }

    @Override
    public boolean retainAll(Collection<?> c) {
        return false;
    }

    @Override
    public void clear() {

    }

    @Override
    public T get(int index) {
        return null;
    }

    @Override
    public T set(int index, T element) {
        return null;
    }

    @Override
    public void add(int index, T element) {

    }

    @Override
    public T remove(int index) {
        return null;
    }

    @Override
    public int indexOf(Object o) {
        return 0;
    }

    @Override
    public int lastIndexOf(Object o) {
        return 0;
    }

    @Override
    public ListIterator<T> listIterator() {
        return null;
    }

    @Override
    public ListIterator<T> listIterator(int index) {
        return null;
    }

    @Override
    public List<T> subList(int fromIndex, int toIndex) {
        return null;
    }
}

猜你喜欢

转载自blog.csdn.net/Wengzhengcun/article/details/86749436