Как защитить методы класса Singleton для обеспечения безопасности потоков в Java? - PullRequest
2 голосов
/ 14 февраля 2011

У меня есть потокобезопасный класс Singleton с двойной проверкой, который содержит LinkedList с методами get / set / size в классе Singleton. Затем у меня есть простой класс пула, который использует этот класс Singleton для управления пулом объектов.

Мой вопрос заключается в том, как защитить методы get / set как в синглтоне, так и в классе пула, не используя методы синхронизации. Вот мой код

public class SingletonDoubleCheckedLockingPattern {

    private static SingletonDoubleCheckedLockingPattern s = new SingletonDoubleCheckedLockingPattern();

    private LinkedList<Object> linkedList;

    public int GetListObjectCount() {
        return linkedList.size();
    }

    public Object GetObjectFromList() {
        return linkedList.poll();
    }

    public void SetObjectFromList(Object ee) {
        linkedList.add(ee);
    }

    private SingletonDoubleCheckedLockingPattern() {

        linkedList = new LinkedList<Object>();

    }

    /**
     * SingletonHolder is loaded on the first execution of
     * Singleton.getInstance() or the first access to SingletonHolder.INSTANCE,
     * not before.
     */
    private static class SingletonHolder {
        public static final SingletonDoubleCheckedLockingPattern INSTANCE = new SingletonDoubleCheckedLockingPattern();
    }

    public static SingletonDoubleCheckedLockingPattern getInstance() {
        return SingletonHolder.INSTANCE;
    }

    // avoid cloning
    public final Object clone() throws CloneNotSupportedException {
        throw new CloneNotSupportedException();
    }

}

public class SingletonObjectPool  {

    private int maxlistValue = 10;


    public Object GetObject() 
    {
        int listCount = SingletonDoubleCheckedLockingPattern.getInstance().GetListObjectCount();
        if(listCount > 0)
        {
            return SingletonDoubleCheckedLockingPattern.getInstance().GetObjectFromList();
        }
        return null;
    }


    public void SetObject() 
    {
        int listCount = SingletonDoubleCheckedLockingPattern.getInstance().GetListObjectCount();
        if(listCount < maxlistValue)
        {
            SingletonDoubleCheckedLockingPattern.getInstance().SetObjectFromList(new Object());
        }

    }


}

Ответы [ 2 ]

2 голосов
/ 14 февраля 2011

Вы можете использовать BlockingQueue, который является потокобезопасным. Вам не нужно проверять, является ли коллекция пустой, прежде чем пытаться удалить элемент, у коллекции есть метод для этого.

Чтобы упростить ваш код и сделать его потокобезопасным, вы можете сделать.

public class SingletonObjectPool  {
    private static final int maxlistValue = 10;
    private static final BlockingQueue queue 
        = new ArrayBlockingQueue(maxListValue);

    public static Object getObject() {
        return queue.poll();
    }


    public static void addObjectAsRequired() {
        queue.offer(new Object());
    }
}
0 голосов
/ 14 февраля 2011

Единственный способ, которым я могу думать, что вы можете возможно вызывать методы, такие как GetListObjectCount без использования synchronized, - это если сам список является поточно-ориентированным и будет вести себя разумно при вызове этого метода перед лицом одновременных изменений.

В этом случае никаких других проблем не будет, так как ссылка на сам список никогда не изменится. Вы можете объявить его как final, чтобы сделать это совершенно ясным, и чтобы компилятор предупреждал любого, кто пытается переназначить список. (Если бы это было требованием, ссылка должна была бы быть, по крайней мере, volatile, но это открывает много других вопросов относительно правильности нескольких операций вашего класса).

Суть в том, что «безопасность потоков» - это не простая бинарная концепция. Нельзя просто сказать, что определенный класс и / или метод являются поточно-ориентированными; скорее речь идет о том, какие комбинации методов вы можете вызывать с полезной и правильной семантикой.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...