Глобальные данные записываются одним потоком и читаются несколькими потоками - PullRequest
1 голос
/ 16 марта 2012

Существует один поток и только один поток, который будет записывать / изменять структуру данных.Структура данных имеет одно поле, которое является дескриптором сокета, открытым потоком записи.Два других потока будут читать структуру данных и должны будут что-то делать (например, опросить сокеты, хранящиеся в структуре для входных данных).

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

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

PS Я использую потоки POSIX, работающие в среде Linux

Ответы [ 6 ]

1 голос
/ 16 марта 2012

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

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

1 голос
/ 16 марта 2012

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

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

Более длинный ответ: подумайте о связанном списке. Подумайте о добавлении элемента или его удалении. Обычно вам нужно изменить несколько аспектов этого списка, например, вам нужно изменить 2 указателя. Теперь спросите себя: что будет, если:

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

EDIT

Как отмечает Благовест Буюклиев в комментариях, структуры данных без блокировок обычно обеспечивают большую производительность, чтобы вы могли исследовать этот маршрут.

0 голосов
/ 16 марта 2012

Вам нужно избегать гонок, как уже говорили другие. Если вы не хотите использовать мьютекс для защиты ваших данных, современный C, C11 вводит атомарные операции на уровне языка. Пока это не получит более широкую поддержку напрямую, вы можете использовать расширение компилятора как для gcc и совместимых (clang, icc, opencc) или через макросы, которые эмулируют новый интерфейс .

0 голосов
/ 16 марта 2012

Хм .. вы можете уйти без блокировки, но вам нужно быть осторожным :) Каждый элемент в массиве / списке / любом контейнере может иметь перечисление состояния, может быть:

перечисление состояния{EstFree, EstInUse, EstDeletePending}

Чтобы добавить запись, поток записи выполняет итерацию массива / списка и использует первую запись с состоянием 'EstFree'.Если его нет, он создает другой элемент и добавляет его в конце.

Чтобы «удалить» запись «EstInUse», установите ее состояние «EdeletePending».Когда поток, использующий этот элемент, замечает изменение состояния, он знает, что остановить опрос, поэтому он устанавливает состояние в «EstFree» и завершает работу.

0 голосов
/ 16 марта 2012

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

В ответ на вопрос о трубопроводах для межпроцессного взаимодействия. Я рекомендовал использовать каналы, потому что вы говорили об использовании сокетов. Розетки, которые предназначены для межсетевого общения. В этом посте говорится о различиях между каналами и сокетами в ядре Linux. Для локальных машинных коммуникаций трубы бьют сокеты с точки зрения скорости и эффективности, поскольку они имеют намного более простую реализацию, чем сокеты. И, наконец, у вас не возникнет проблем с многопоточностью, поскольку ядро ​​позаботится о вас.

0 голосов
/ 16 марта 2012

Хотя это зависит от структуры данных, для большинства структур данных ответ таков: Конечно.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...