Нужна ли этой модели мьютекс? - PullRequest
2 голосов
/ 04 мая 2011

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

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

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

Контроллер-клиент добавляет задачи в вектор.

Теперь, когда существует вектор, совместно используемый двумя потоками, может возникнуть условие гонки, но поскольку один поток добавляет только объекты, а другой только всплывает объекты, это необходимо? Я пытался создать блок-схему с этой проблемой, но, возможно, это не ясно. Я действительно не знаю, как создать блок-схему: enter image description here

Я использую std::vector <CustomClass> из C ++, чтобы понять это.

Заранее спасибо,
ief2

РЕДАКТИРОВАТЬ: Дополнительный вопрос: нужен ли для вызова vector.size() мьютекс?

Ответы [ 7 ]

7 голосов
/ 04 мая 2011

Да, для этого нужен мьютекс.

Выполнение

vector.pop_front() и vector.push_back() в одно и то же время приведет к разного рода беспорядкам - при условии, что нестандартный vector.pop_front() делает то, что подразумевает название.

Примечание: используйте очередь или список, а не вектор

3 голосов
/ 04 мая 2011

Вы должны контролировать доступ к вектору. Вы не хотите пытаться одновременно толкать и хлопать.

1 голос
/ 05 мая 2011

Мне интересно, как реализован контролируемый клиент. Это цикл, который продолжает проверять очередь задач? Если это так, и вы считаете, что эффективность важнее, вы можете реализовать очередь задач в виде односвязного списка и при этом иметь поточно-ориентированную и свободную от блокировок реализацию. Все, что вам нужно, это тупой узел в списке, а голова указывает на этот тупой узел. Пустой список представлен, поскольку следующее поле тупого узла - ноль. Когда вы щелкаете, вы просто перемещаете голову от текущего тупого узла к следующему узлу, который становится новым тупым узлом. Когда вы нажимаете, вы просто добавляете задачу, поскольку список не пустой (содержит, по крайней мере, тупой узел). Это работает только для двухпоточного сценария.

1 голос
/ 04 мая 2011

Да, вам нужен мьютекс. На многопроцессорной машине оба потока могут пытаться одновременно выдвигать и выталкивать. Хорошей идеей может быть также условная переменная, указывающая, когда нужно что-то обработать.

0 голосов
/ 04 мая 2011

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

Это останавливает ненужные циклы ЦП проверки команд в пустом векторе.

0 голосов
/ 04 мая 2011

Блок-схемы обычно не очень хорошая идея.

Требуется синхронизация.Вставка или удаление из std::vector в нескольких потоках небезопасно.

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

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

0 голосов
/ 04 мая 2011

Контейнеры STL небезопасны.Так что да, вам нужен механизм блокировки (то есть мьютекс), чтобы сделать контейнер потокобезопасным.

Вы можете прочитать этот вопрос SO , чтобы увидеть пример упаковки очереди STL для обеспечения безопасности потоков.

...