форк в многопоточной программе - PullRequest
23 голосов
/ 06 августа 2009

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

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

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

Ответы [ 2 ]

17 голосов
/ 06 августа 2009

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

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

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

0 голосов
/ 06 августа 2009

Это действительно довольно просто. Проблемы с несколькими потоками и процессами всегда возникают из-за общих данных. Если нет общих данных, то возможных проблем не возникает.

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

...