2010-05-07 2 views
6

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

Здесь структура многопоточного приложения (извините за грубость):

    MainThread 
       /  \ 
       /   \ 
       /   \ 
     Thread A    Thread B 
    /  \   /  \ 
    /  \   /  \ 
    /   \  /   \ 
Thread A_1  Thread A_2 Thread B_1 Thread B_2 

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

Таким образом, структура данных создается в MainThread, будет изменена в начерченной нити (Thread A и т. Д.), Специфичной для этого потока, а затем переменная-член из этой структуры данных отправляется в потоки Letter_Numbered.

В настоящее время класс с буквой нитей имеет переменную-член и, когда класс построен, структура данных из mainthread передается по ссылке, вызывая конструктор копирования, так что в потоке с надписью есть своя собственная копия для воспроизведения.

Буквенный поток просто принимает строковую переменную из структуры данных в потоке с надписью. Мой вопрос в том, что это неприемлемо? Есть ли лучший способ обеспечить, чтобы каждый потоковый поток получал свою собственную структуру данных?

Извините за несколько плохое объяснение, пожалуйста, оставьте комментарии, и я попробую уточнить.

EDIT: Итак, мой конструктор поточных нитей должен принимать значение VALUE структуры данных, а не ссылку?

+0

Возможно, расскажите немного о том, чего вы хотите достичь. Я немного озадачен использованием двух последовательных потоков - вы имеете в виду, что один начинается, когда другой заканчивается? – mdma

+0

+1 для хорошо сформулированного вопроса –

+0

@mdma: вы имеете в виду lettered_numbered? Если да, то да, пронумерованная нить срабатывает с первого lettered_numbered, ждет, когда она будет закончена (или ошибка), и выйдет из второго буквенного номера. Это помогает? – Robb

ответ

5

У меня была бы каждая нить, создающая ее собственную копию структуры данных, например. вы передаете структуру в конструкторе, а затем явно создаете локальную копию. Тогда вам гарантируется, что потоки имеют разные копии. (Вы говорите, что это передается по ссылке, и что это вызывает конструктор копирования. Я думаю, вы имеете в виду пропуск по значению? Я считаю, что лучше явно сделать копию, не оставлять никаких сомнений и сделать ваше намерение ясным. пришлите и измените свой пропуск по значению, чтобы перейти по ссылке в качестве «умной оптимизации».)

EDIT: Удалено комментарий о строках. По какой-то причине я принимал .NET.

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

+0

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

+3

Строки в C++ не являются неизменными. – stonemetal

+0

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

1

Вы посмотрели boost threads?

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

Это очень похоже на то, как Java реализует потоки, и большую часть времени он делает с точки зрения дизайна.

+0

Насколько я хотел бы идти по ускоренному маршруту, проект в настоящее время находится в состоянии, когда для этого потребуется достаточно перезаписать, где меня будут сбивать начальники. – Robb

+0

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

+0

Да, это на самом деле то, что я делаю, за исключением использования прохода по ссылке структуры данных. – Robb

3

Существует модель называется Active Object Pattern, где каждый объект выполняет в своем собственном потоке. Такие рамки, как ACE, поддерживают это. Если у вас есть доступ к таким фреймворкам, вы должны использовать их.В любом случае, я считаю, что создать новый экземпляр объекта и позволить ему выполнять в своем собственном потоке гораздо более чистый, чтобы вызвать экземпляр-копию, чтобы сделать копию объекта. Еще посмотрите, можете ли вы поместить решение, которое использует Thread Local Storage.

1

Вы aparently делаете копию данных для каждой треги и все работает? то нет проблем.

Вот некоторые дополнительные мысли:

  • Если данные только для чтения, вы можете использовать один структуру и все будет в порядке, до тех пор, как каждое чтение является небольшими и быстро (основными типами)
  • Если данные должны быть записаны, но «закрыты» (или содержатся) для каждого потока, то отправьте копию в каждый поток (что вы делаете). Предостережение: Я предполагаю, что данные не слишком большие, а копия не питается много ресурсов.
  • Если данные должны быть записаны и новые значения разделены между потоками, тогда вам нужно подумать об этом (прочитайте на нем) и создать правильный дизайн. Мне нравится транзакционный объект для централизации каждой операции чтения/записи потоков. Как крошечная база данных в памяти. Проверьте поток мьютексов, семафоров и критических разделов). Работа с огромным набором данных Я использовал базу данных для централизации запросов (см. ODBM). Вы также можете проверить существующие библиотеки массового обслуживания сообщений (например, MSMQ), чтобы упорядочить и синхронизировать данные.

Надеюсь, это поможет.

+0

К счастью, структура данных на самом деле не будет разделяться между потоками, кроме описанных выше. Поэтому, если структура данных содержится внутри каждого потока (и каждый поток имеет свою структуру данных OWN), для мьютексов не должно быть много пользы. – Robb

0

Кажется маловероятным, что вы хотите, чтобы каждый поток работал с данными, а затем, по крайней мере, иногда не реагировал на другой поток на то, что другой поток сделал с работой другого потока данных. Если вы действительно независимы, то ни один другой поток не позаботится о работе, которую сделал другой поток, тогда я предлагаю сделать копию данных, иначе в случае, когда вы захотите работать в одном потоке и сделать этот результат этой работы, доступной для другого потока, я бы предложил вам передать ссылочный/указатель на объект вокруг, а затем защитить доступ к нему через блокировки, чтобы потоки могли работать с ним, правильно, я предлагаю многочиповую одиночную запись блокировка.

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