2013-02-16 6 views
0

У меня есть одна тема FileScanner, которая добавляет новые файлы в список и несколько потоков FileParser, которые получают новые файлы, и каждый анализирует свои собственные файлы. для синхронизации я поместил добавление в список и прочитал из списка в блоке с синхронизированным ресурсом. проблема в том, что иногда FileScanner Thread, похоже, голодает и не входит в синхронизированный блок, ожидая появления других потоков FileParser для выпуска ресурса (списка). Мой вопрос: если я установил максимальный приоритет для моего FileScanner и, как минимум, для других потоков FileParser, устранит проблему? Другими словами, влияет ли приоритет нити на JVM, чтобы выбирать между потоками для предоставления доступа к синхронизированному блоку? Спасибо.Действительно ли приоритет нити влияет на доступ к синхронизированному блоку?

UPDATE:

private List<ScannerFile> scannedFiles = Collections.synchronizedList(new LinkedList<ScannerFile>()) ; 

это называется в моей FileScanner теме:

synchronized(scannedFiles){ 
     for(ScannerFile f: newList) 
      try{ 
       scannedFiles.add(f); 
      } 
      catch(ConcurrentModificationException e){ 
       logger.error(e); 
      } 
    } 

И это называется в моих FileParser нитей:

synchronized(scannedFiles){ 
    try{ 
     for(ScannerFile f: scannedFiles){ 
      if(parserName.equals(f.getParserName()) && f.isNew() == true){ 
       listNewFiles.add(f); 
      }   
     } 
     return listNewFiles; 
    } 
    catch(ConcurrentModificationException e){ 
     logger.trace(e); 
     return new ArrayList<ScannerFile>(); 
    } 
} 
+2

Использование параллельной коллекции вместо синхронизированной можно было бы уменьшить конкуренцию. – assylias

+0

Я нашел решение в http://tutorials.jenkov.com/java-concurrency/starvation-and-fairness.html –

+0

Не уверен, что вы там нашли. Парень, похоже, пытается переопределить блокировку, которая уже существует в пакете java.util.concurrent. Я не вижу смысла делать это, если честно (если вы не хотите вводить тонкие ошибки). – assylias

ответ

1

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

От «Java Параллелизм на практике» (Гетц и др.):

Избегайте соблазна использовать приоритеты потоков, поскольку они могут увеличить платформы зависимость и может привести к живучести проблемы [...]

Если ваша программа встречает взаимоблокировки, возникает проблема с логикой параллелизма. Изменение приоритетов потоков (в случае маловероятного наилучшего случая) маскирует эту проблему или (в вероятном случае) вводит неопределенное, специфическое для аппаратного обеспечения поведение.

Описание проблемы, которая выглядит как пример для ReadWriteLock. Но без краткого примера вашего кода трудно дать хороший совет.

+0

@Pyanja Я добавил фрагмент кода, надеясь, что это поможет. спасибо –

1

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

+0

спасибо за ваш ответ, однако речь идет не о создании или нарушении синхронизации. когда поток находится в синхронизированном блоке, другие потоки будут ждать, пока поток внутри блока не завершится, они ждут, но они не стоят в очереди. Я имею в виду, что следующий поток для ввода не выбирается алгоритмом FIFO. Я имею в виду, что это похоже на случайное или что-то еще. Я хочу знать, влияет ли приоритет на этот вопрос. –

+1

С классами Lock в параллельном пакете вы можете сделать их * справедливыми * за небольшую цену в эффективности. Вы не можете сделать это с синхронизированными блоками. Без справедливости выбор следующего потока осуществляется ОС, где приоритеты влияют, но определяют планирование. –

+0

Спасибо @ Ralf H, я проверю параллельный пакет для справедливости. –

0

Существует логическая ошибка. Это должно работать (я не имел IDE для повторного подтверждения):

LinkedBlockingQueue<ScannerFile> newList = new LinkedBlockingQueue<>(); 
LinkedBlockingQueue<ScannerFile> scannedFiles = new LinkedBlockingQueue<>(); 
for(;;){ 

try{ 
ScannerFile f = newList.get(); 
scannedFiles.add(f); 
} 
catch(InterruptedException ex{ 
Thread.currentThread.interrupt(); 
//log 
break; 
} 
} 

ThreadParser будет идти, как это:

for(;;){ 
try{ 
ScannedFile f= scannedFiles.get(); 
//other logic goes here 
}catch(InterruptedException ex{ 
Thread.currentThread.interrupt(); 
//log 
break; 
} 
} 
+0

Спасибо за ваш подробный ответ, однако, я думаю, вы неправильно поняли проблему. моя программная логика прекрасна, и вся программа работает отлично 99% всех времен. только один раз в неделю, ThreadScanner Thread не обнаруживает ни одного файла, однако в данный момент работают другие Threads. Я знаю все это, потому что я регистрирую каждый шаг. в любом случае мой вопрос является общим, я просто включил код, чтобы понять это. –

Смежные вопросы