К наиболее частым оплошностям
и ошибкам многопоточных программах относятся:
передача указателя на стек вызывающего потока как аргумента для нового
потока;
доступ к глобальной памяти без использования механизмов синхронизации;
создание тупиков, вызванных двумя потоками, при попытке получить права
на одну и ту же пару глобальных ресурсов в различном порядке (один
поток управляет первым ресурсом, а второй управляет другим ресурсом
и ни один может продолжать выполнение до освобождения нужного ресурса);
попытка повторно получить доступ к уже захваченному ресурсу (рекурсивный
тупик);
создание скрытого промежутка при синхронизации. Это происходит, когда
сегмент кода, защищенный механизмом синхронизации, содержит вызов функции,
которая освобождает и затем повторно создает механизм синхронизации
прежде, чем управление возвращается к вызывающему потоку. В результате
вызывающему кажется, что глобальные данные были защищены, хотя это
не соответствует действительности;
смешивание сигналов UNIX с потоками - лучше использовать sigwait()
для того, чтобы обрабатывать асинхронные сигналы;
невнимание к тому факту, что потоки по умолчанию создаются с типом
PTHREAD_CREATE_JOINABLE и должны быть утилизованы через
pthread_join(). Следует обратить внимание, что pthread_exit()
не освобождает выделенную память;
создание глубоко вложенных, рекурсивных обращений и использование
больших автоматических массивов может
вызвать затруднения, потому что
многопоточные программы имеют более ограниченный размер стека, чем
однопоточные;
определение неадекватного размера стека или использование стека не
по умолчанию.