Nano Hash - криптовалюты, майнинг, программирование

Использовать не потокобезопасный список для LinkedBlockingQueue

Мне интересно, почему LinkedBlockingQueue не работает если мы изменим базовую структуру данных на небезопасный для потоков список, такой как java.util.LinkedList? Я получаю исключение NoSuchElementException, когда пробовал. Разве он не защищен блокировкой (takeLock), которая делает его потокобезопасным?

private final List<E> list;
private final ReentrantLock takeLock;
private final ReentrantLock putLock;
private final Condition     notFull;
private final Condition     notEmpty;
private final AtomicInteger count;

public LinkedBlockingQueue() {
    takeLock = new ReentrantLock();
    putLock = new ReentrantLock();
    notFull = putLock.newCondition();
    notEmpty = takeLock.newCondition();
    count = new AtomicInteger(0);
    list = new LinkedList<E>();
}

public E get() {
   E item = null;
   int c = -1;
   try {
      takeLock.lockInterruptibly();
      while (count.get() == 0) notEmpty.await();

      // original -> item = dequeue();
      item = list.remove();   // NoSuchElementException

      c = count.getAndDecrement();
   } 
   catch (InterruptedException ie) {} 
   finally {
      takeLock.unlock();
   }

   if (c == capacity) signalNotFull();
   return item;
}

public void put(E e) {
   int c = -1;
   try {
      putLock.lockInterruptibly();
      while (count.get() == BOUND_SIZE) notFull.await();

      // original -> enqueue(node);
      list.add(e);

      c = count.getAndIncrement();
   } 
   catch (InterruptedException ie) {} 
   finally {
      putLock.unlock();
   }

   if (c == 0) signalNotEmpty();
}

  • Как вы добавляете элементы в список? 22.02.2015
  • В чем разница между count и size, putLock и takeLock? 22.02.2015
  • Кроме того, какое это имеет отношение к LinkedBlockingQueue? 22.02.2015
  • Ваш код выглядит довольно небезопасным для потоков. (Блокировки волшебным образом не делают код потокобезопасным) 22.02.2015
  • это почему ? единственное отличие от исходной реализации (docjar.com/ html/api/java/util/concurrent/) просто переключается на java.util.LinkedList 22.02.2015
  • LinkedLists не являются потокобезопасными. (это не означает, что вы не можете использовать их из нескольких потоков; это означает, что вы не можете использовать их из нескольких потоков одновременно). Если вы попытаетесь использовать один из нескольких потоков одновременно, нет никаких гарантий (в частности, такие вещи, как если вы добавите элемент, другой поток может получить элемент, не гарантируются) 22.02.2015
  • Я понимаю, что LinkedList не является потокобезопасным, как я уже упоминал в вопросе. Когда вы смотрите на реализацию docjar.com/html/ api/java/util/concurrent/, который использует и поддерживает связанный список (но не из java.util.LinkedList). Он определяет этот новый внутренний класс Node для связывания всех элементов. В чем отличия? и что делает его потокобезопасным? 22.02.2015
  • ConcurrentBlockingQueue очень тщательно разработан для обеспечения безопасности потоков; LinkedList нет. (Во-первых, обратите внимание, что enqueue и dequeue не используют одни и те же ссылки, за исключением указателей next... Я не уверен, почему одновременное управление указателями next допустимо) 22.02.2015
  • Кстати, если вы получили исключение при самом первом вызове get, возможно, у вас где-то есть ошибка. Проблемы безопасности потоков обычно непредсказуемы и случаются только иногда. 22.02.2015

Ответы:


1

Вы используете два отдельных объекта блокировки:

takeLock = new ReentrantLock();
putLock = new ReentrantLock();
notFull = putLock.newCondition();
notEmpty = takeLock.newCondition();

Это не правильно. Прежде всего, вы должны использовать один и тот же объект блокировки как для операций ввода, так и для операций взятия. Кроме того, вы должны создать свои условия, используя тот же объект блокировки.

lock = new ReentrantLock();
notFull = lock.newCondition();
notEmpty = lock.newCondition();

И вы должны заменить использование takeLock и putLock заданной ссылкой на блокировку.

http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/locks/Lock.html http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/locks/Condition.html

22.02.2015
  • Это сработает, но тогда вы не сможете вызывать put и take одновременно. который будет вести себя так же, как синхронизация обоих методов. текущая реализация docjar.com/html/api/java /util/concurrent/ использует 2 блокировки 22.02.2015
  • Упомянутая вами реализация работает с двумя ссылками, головной и последней. putLock защищает последнюю ссылку, а takeLock защищает заголовок. Следовательно, две блокировки защищают две разные ссылки. putLock гарантирует видимость и атомарность операций по последней ссылке. Точно так же takeLock работает со ссылкой на голову. Гарантии видимости между читателями и писателями уже задокументированы в коде. В вашем примере вы вносите изменения в объект в замке и ожидаете, что он будет виден другому потоку под другим замком. Это не работает таким образом. 22.02.2015
  • это имеет смысл. Это ответ, который я ищу. Спасибо 22.02.2015
  • Новые материалы

    Кластеризация: более глубокий взгляд
    Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

    Как написать эффективное резюме
    Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

    Частный метод Python: улучшение инкапсуляции и безопасности
    Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

    Как я автоматизирую тестирование с помощью Jest
    Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

    Понимание расстояния Вассерштейна: мощная метрика в машинном обучении
    В обширной области машинного обучения часто возникает необходимость сравнивать и измерять различия между распределениями вероятностей. Традиционные метрики расстояния, такие как евклидово..

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..