Сделайте ваши темы максимально простыми.
Старайтесь не использовать глобальные переменные.Глобальные константы (фактические константы, которые никогда не меняются) - это хорошо.Когда вам нужно использовать глобальные или общие переменные, вам нужно защитить их с помощью мьютекса / блокировки (семафор, монитор, ...).
Убедитесь, что вы действительно понимаете, как работают ваши мьютексы.Существует несколько различных реализаций, которые могут работать по-разному.
Постарайтесь организовать свой код так, чтобы критические секции (места, где вы держите какой-либо тип блокировки) были как можно быстрее.Имейте в виду, что некоторые функции могут блокироваться (спят или ждут чего-либо и не позволяют ОС продолжать работу этого потока в течение некоторого времени).Не используйте их во время удержания каких-либо блокировок (за исключением случаев, когда это абсолютно необходимо или во время отладки, поскольку иногда могут отображаться другие ошибки).
Постарайтесь понять, что на самом деле делает больше потоков.Слепое наложение большего количества потоков на проблему очень часто будет ухудшать ситуацию.Различные потоки конкурируют за процессор и за блокировки.
Предотвращение тупиковых ситуаций требует планирования.Старайтесь избегать приобретения более одного замка одновременно.Если это неизбежно, выберите порядок, который вы будете использовать для получения и снятия блокировок для всех потоков.Убедитесь, что вы знаете, что на самом деле означает тупик.
Отладка многопоточных или распределенных приложений затруднена.Если вы можете выполнять большую часть отладки в однопоточной среде (возможно, даже просто заставляя другие потоки спать), вы можете попытаться устранить ошибки, не связанные с многопоточностью, прежде чем переходить к многопоточной отладке.
Всегда думайтео том, что другие темы могут быть до.Прокомментируйте это в своем коде.Если вы делаете что-то определенным образом, потому что знаете, что в то время никакие другие потоки не должны получать доступ к определенному ресурсу, напишите большой комментарий, говорящий так.
Возможно, вы захотите заключить вызовы в блокировки / разблокировки мьютекса в другихфункции, такие как:
int my_lock_get (блокировка lock_type, файл const char *, строка без знака, const char * msg) {
thread_id_type me = this_thread();
logf("%u\t%s (%u)\t%s:%u\t%s\t%s\n", time_now(), thread_name(me), me, "get", msg);
lock_get(lock);
logf("%u\t%s (%u)\t%s:%u\t%s\t%s\n", time_now(), thread_name(me), me, "in", msg);
}
И аналогичная версия дляразблокировать.Обратите внимание, что функции и типы, используемые в этом, все составлены и не слишком основаны на каком-либо одном API.
Используя что-то подобное, вы можете вернуться в случае ошибки и использовать Perl-скрипт или что-то подобноезапускать запросы к вашим журналам, чтобы выяснить, где что-то пошло не так (например, при сопоставлении блокировок и разблокировок).
Обратите внимание, что функциональность печати или ведения журналов может также нуждаться в блокировках.Во многих библиотеках это уже встроено, но не во всех.Эти блокировки не должны использовать печатную версию функций lock_ [get | release], иначе у вас будет бесконечная рекурсия.