Вот официальный ответ от Qt-JIRA:
«Вы получаете доступ к своим m_connectionParams из двух разных потоков без блокировки. Основной поток записывает его в connectToEmulatorService (), а рабочий поток читает его в connectToEmulatorServiceImpl (). Если основной поток записывает снова, в то время как рабочий поток только читает предыдущую итерацию, вы получаете сбой. Это наиболее очевидная проблема.
Однако, даже если вы заблокировали мьютекс для доступа для m_connectionParams, это все равно будет небезопасно. Вариант, который у вас есть, это внутренне QJSValue. Чтобы преобразовать это в карту, мы должны вызвать глубоко в движке JavaScript, создать области и взаимодействовать с кучей JavaScript. любой другой JavaScript выполняется одновременно в другом потоке, у вас проблемы.
Просто извлеките QVariantMap из основного потока и передайте его вашему функтору в качестве параметра. "
Итак, иметь копию QVariant недостаточно ... это где-то глубоко внутри источников Qt.
Нет, методы не должны синхронизироваться, и Вы не должны определять методы; они уже находятся в ConcurrentLinkedQueue, просто используют их. ConcurrentLinkedQueue делает всю блокировку и другие операции, в которых Вы нуждаетесь внутренне; Ваш производитель (производители) добавляет данные в очередь, и Ваши потребители опрашивают относительно него.
Первый, создайте свою очередь:
Queue<YourObject> queue = new ConcurrentLinkedQueue<YourObject>();
Теперь, где бы вы ни были создавая Ваши объекты производителя/потребителя, передачу в очереди, таким образом, они должны где-нибудь поместить свои объекты (Вы могли использовать метод set для этого, вместо этого, но я предпочитаю делать такого рода вещь в конструкторе):
YourProducer producer = new YourProducer(queue);
и:
YourConsumer consumer = new YourConsumer(queue);
и добавляют материал к нему в Вашем производителе:
queue.offer(myObject);
и вынимают материал в Вашем потребителе (если очередь будет пуста, то опрос () возвратит пустой указатель, так проверьте его):
YourObject myObject = queue.poll();
Для большего количества информации см. РЕДАКТИРОВАНИЕ Javadoc
, Если необходимо заблокировать ожидание очереди, чтобы не быть пустыми, Вы, вероятно, хотите использовать LinkedBlockingQueue и использовать взятие () метод. Однако LinkedBlockingQueue имеет максимальную способность (значения по умолчанию к Целому числу. MAX_VALUE, который является более чем двумя миллиардами), и таким образом может или может не быть соответствующим в зависимости от Ваших обстоятельств.
, Если у Вас только есть один материал помещения потока в очередь и другой материал вынимающего потока из очереди, ConcurrentLinkedQueue является, вероятно, излишеством. Это больше для того, когда у Вас могут быть сотни или даже тысячи потоков, получающих доступ к очереди одновременно. Ваши потребности будут, вероятно, удовлетворены при помощи:
Queue<YourObject> queue = Collections.synchronizedList(new LinkedList<YourObject>());
А плюс этого - то, что это соединяет экземпляр (очередь), таким образом, можно синхронизироваться на очереди для обеспечения атомарности составных операций (как объяснил Jared). Вы не МОЖЕТЕ сделать этого с ConcurrentLinkedQueue, поскольку все операции СДЕЛАНЫ, не соединяя экземпляр (использующий java.util.concurrent.atomic переменные). Вы НЕ должны будете делать этого, если Вы захотите заблокироваться, в то время как очередь пуста, потому что опрос () просто возвратит пустой указатель, в то время как очередь пуста, и опрос () является атомарным. Проверьте, чтобы видеть, возвращает ли опрос () пустой указатель. Если это делает, ожидает (), то попробовало еще раз. Никакая потребность заблокировать.
Честно, я просто использовал бы LinkedBlockingQueue. Это - все еще излишество для Вашего приложения, но разногласия - это, будет хорошо работать. Если это не достаточно производительно (ПРОФИЛЬ!), можно всегда пробовать что-то еще, и это означает, что Вы не должны иметь дело ни с КАКИМ синхронизируемым материалом:
BlockingQueue<YourObject> queue = new LinkedBlockingQueue<YourObject>();
queue.put(myObject); // Blocks until queue isn't full.
YourObject myObject = queue.take(); // Blocks until queue isn't empty.
Все остальное - то же. Помещенный , вероятно не заблокируется, потому что Вы, вероятно, не поместите два миллиарда объектов в очередь.
Это в основном дубликат другого вопроса .
Вот раздел того ответа, который относится к этому вопросу:
Делают я должен сделать свою собственную синхронизацию, если я использую java.util. ConcurrentLinkedQueue?
Атомарные операции на параллельных наборах синхронизируются для Вас. Другими словами, каждый отдельный вызов очереди гарантируется ориентированный на многопотоковое исполнение без любого действия с Вашей стороны. То, что не , гарантировало ориентированный на многопотоковое исполнение, любые операции, которые Вы выполняете на наборе, которые являются неатомарными.
, Например, это ориентировано на многопотоковое исполнение без любого действия с Вашей стороны:
queue.add(obj);
или
queue.poll(obj);
Однако; неатомарные вызовы очереди не автоматически ориентированы на многопотоковое исполнение. Например, следующие операции не автоматически ориентированы на многопотоковое исполнение:
if(!queue.isEmpty()) {
queue.poll(obj);
}
, Что последний не ориентирован на многопотоковое исполнение, поскольку очень возможно, что между временем isEmpty назван и опрос времени называют, другие потоки добавят или удалят объекты из очереди. Ориентированный на многопотоковое исполнение способ выполнить это похож на это:
synchronized(queue) {
if(!queue.isEmpty()) {
queue.poll(obj);
}
}
Снова... атомарные вызовы очереди автоматически ориентированы на многопотоковое исполнение. Неатомарные вызовы не.
Используйте , опрос для получения первого элемента, и добавляет для добавления нового последнего элемента. Вот именно, никакая синхронизация или что-либо еще.
ConcurentLinkedQueue является очень эффективным, ожидают/блокируют бесплатная реализация (см. javadoc для ссылки), таким образом, не только Вы не должны синхронизироваться, но и очередь ничего не заблокирует, таким образом будучи фактически с такой скоростью, как не синхронизируемой (не ориентированный на многопотоковое исполнение) один.
Просто используйте его, поскольку Вы были бы непараллельный набор. Параллельное [Набор], классы обертывают регулярные наборы так, чтобы Вы не думали о синхронизирующемся доступе.
Редактирование: ConcurrentLinkedList не является на самом деле просто оберткой, а скорее лучшей параллельной реализацией. Так или иначе Вы не должны волноваться о синхронизации.