Семафор с очередью

280
29 октября 2017, 17:30

есть семафор:

public class Semaphore{
    private Queue<Object> queue;
    private int current;
    private int permits;
    public Semaphore(int permits) {
        this.permits = permits;
        this.queue = new LinkedList<>();
    }
    public void enter() throws InterruptedException {
        Object object = new Object();
        synchronized (object) {
            try {
                if (current > permits) {
                    this.queue.add(object);
                    object.wait();
                } else {
                    current++;
                }
            } catch (InterruptedException e) {
                throw e;
            }
        }
    }
    public void leave() {
        Object object = queue.poll();
        current--;
        if(null == object) {
            return;
        }
        synchronized (object) {
            object.notify();
        }
    }

Объясните почему это работает неправильно. Синхронизация вообще отсутствует.

Answer 1
  1. Ну кто же использует не LinkedList в многопоточном коде? Почему не взять какую-то из специальных коллекций для многопоточности?

  2. Непонятно а какую синхронизацию вы тут собственно ожидаете?

    public void enter() throws InterruptedException {
        Object object = new Object();
        synchronized (object) { // никакой синхронизации нет, 
                                // так как это новый объект
            try {
                if (current > permits) {
                    this.queue.add(object);
                    object.wait(); // ну да зависнет до notify, но 
                            // это последняя инструкция и все равно никакой разницы вы не увидите
                } else {
                    current++;
                }
            } catch (InterruptedException e) {
                throw e;
            }
        }
    }
    
     public void leave() {
        Object object = queue.poll(); // для каждого потока будет скорее всего отдельный объект и синхронизация не имеет большого смысла 
        current--;
        if(null == object) {
            return;
        }
        synchronized (object) { 
            object.notify();
        }
    }

Итого в методе enter собственно создается новый объект и синхронизации нет. В методе leave каждый раз после получения объекта, он будет удалятся из списка (в идеале, вообще говоря LinkedList не предназначен для нескольких потоков и результат может быть любым), поэтому синхронизации не будет, notify пошлет сигнал объекту, но поскольку он все равно на последней строчки ничего не произойдет. Что конкретно вы хотите добиться таким кодом и как его вызываете?

READ ALSO
scroll списка пользователей

scroll списка пользователей

Новичок в андройд-разработке, мне нужно сделать скролл списка пользователей в виде плитки, чтобы "за раз" было видно 6 пользователейПодскажите,...

239
Gradle не видит сторонние библиотеки

Gradle не видит сторонние библиотеки

Обновил Gradle и он перестал видеть две сторонние библиотеки, которые были добавлены через "File dependency" (те

223
Вопрос по интерфейсу IFormatable в C#

Вопрос по интерфейсу IFormatable в C#

Здравствуйте, хочу разобраться с IFormatable и IFormatProvider

263
Проблема с вечным циклом в С#

Проблема с вечным циклом в С#

В коде ниже бесконечно выполняется (повторяется) одно действиеВ чем может быть проблема?

240