Сценарий: глобальные переменные в DLL, которые используются многопоточными приложениями - PullRequest
5 голосов
/ 30 ноября 2010

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

Предположим, я создал DLL, экспортирующую некоторые функции, написанные на C ++, для однопоточного клиента . Эта DLL объявляет множество глобальных переменных, некоторые из которых могут быть константными (только для чтения), а другие - изменяемыми.

В любом случае, позже все изменилось, и теперь я хочу, чтобы одна и та же DLL работала с многопоточным приложением (без изменения DLL); это означает, что несколько потоков получают доступ к функциям и глобальным переменным из DLL и изменяют их ... и так далее. Все это может привести к тому, что глобальные переменные будут содержать несовместимые значения.

Итак, вопрос в том,

Можем ли мы что-то сделать в клиентском коде, чтобы предотвратить множественный доступ к DLL, и в то же время , гарантируя, что каждый поток выполняется в своем собственном контексте (то есть когда он получает доступ к DLL, глобальные значения DLL такие же, как и раньше)?

Ответы [ 2 ]

2 голосов
/ 30 ноября 2010

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

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

Если ваше решение позволяет, часто лучше назначить один поток для изменения любых данных, а все остальные просто читать и никогда не записывать, поскольку одновременный доступ к чтению всегда проще реализовать, чем одновременный доступ к записи ( Boost предоставляет для этого все основные функции, например shared_mutex ).

1 голос
/ 30 ноября 2010

Можем ли мы что-то сделать в клиентском коде, чтобы предотвратить множественный доступ к DLL, и в то же время обеспечить, чтобы каждый поток работал в своем собственном контексте (то есть, когда он получает доступ к DLL, глобальные значения DLL) такие же как и раньше)?

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

Если производительность не является проблемой, будет достаточно одной блокировки для всей DLL, и ее будет проще всего правильно реализовать. Это гарантировало бы, что только один поток обращался (читал или писал) к DLL одновременно.

...