Безопасное совместное использование структуры несколькими потоками - PullRequest
1 голос
/ 14 декабря 2010

В Windows / C ++, если у меня есть структура:

struct ListItem {
    ListItem* next;
    ListItem* prev;
    ...
}

вместе с несколькими потоками, работающими как в основном процессе, так и в нескольких динамически загружаемых библиотеках DLL, и все эти потоки должны совместно использовать вышеуказанноеструктура, как я могу остановить их топать друг на друга?Что-то вроде:

ListItem* list = ...

A

list->next = ...

B

Что я должен поставить на A и B, чтобы предотвратить одновременную работу не более одного потока list->next = ...?

Ответы [ 4 ]

5 голосов
/ 14 декабря 2010

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

Но это не сработает во многих ситуациях.Иногда вам действительно нужно использовать общую структуру данных.В этом случае вам необходимо защитить структуру данных с помощью некоторой формы объекта синхронизации.Boost.Threads предоставляет некоторые кроссплатформенные, и я уверен, что кто-то покажет вам, как их использовать.Поскольку вы спрашивали конкретно о Windows, я покажу вам способ Windows.

Вы можете использовать CRITICAL_SECTION .Во-первых, вам нужно инициализировать критический раздел в главном потоке, прежде чем запускать рабочие потоки:

int main()
{
// ...
  CRITICAL_SECTION cs;
  InitializeCriticalSection(&cs);
// ...
}

Затем передать указатель на cs каждому рабочему потоку.(Это оставлено в качестве упражнения.) В каждом рабочем потоке введите cs, прежде чем работать с вашими данными, и оставьте его, когда закончите.

CRITICAL_SECTION* pcs = ...; // passed in from main thread
EnterCriticalSection(pcs); // this will block until the cs is "available"
list->next = ...
LeaveCriticalSection(pcs); // makes the cs available to other threads

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

Следует отметить, что CRITICAL_SECTION может толькоиспользоваться одним процессом.Если вам нужно использовать объект типа мьютекса в нескольких процессах (а не то, что вам здесь нужно), вам нужно вместо этого использовать с именем mutex .

0 голосов
/ 14 декабря 2010

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

0 голосов
/ 14 декабря 2010
0 голосов
/ 14 декабря 2010

Используйте объекты Windows Mutex, где у вас есть несколько процессов, которые могут обращаться к одному ресурсу.

Если все ваши потоки находятся в одном процессе, вы можете использовать EnterCriticalSection / LeaveCriticalSection.

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