Я скажу вам, что я думаю об этом с точки зрения Windows. Я очень опытный в написании серверных приложений для Windows.
Во-первых, нет абсолютно никаких проблем с созданием семафоров по 20 тыс. Для одного процесса. Это довольно легкий объект ядра. Даже "межпроцессные" семафоры.
Однако я вижу еще одну проблему с вашим дизайном. Вы должны знать, что каждая операция, которую вы выполняете с объектом ядра (таким как семафор / мьютекс), включает в себя тяжелую транзакцию в режиме ядра (системный вызов a.k.a.). Каждый такой вызов может стоить вам около 2 тыс. Циклов ЦП, даже если коллизий нет вообще.
Так что вы можете оказаться в ситуации, когда большая часть процессорного времени тратится только на вызов методов синхронизации.
Напротив, для синхронизации потоков можно использовать взаимосвязанные операции. Они стоят намного дешевле (как правило, десятки циклов ЦП).
Существует также объект с именем критическое сечение . Это своего рода гибрид взаимосвязанного операнда и объекта ядра (который используется в случае реального столкновения). Вы должны проверить, как долго вы обычно блокируете свои элементы. Если это обычно кратковременные блокировки - просто используйте критические разделы, забудьте о сложных блокировках чтения-записи.
Если, тем не менее, вы имеете дело с длительными блокировками, и вам действительно нужна блокировка чтения-записи, и вы видите, что вы тратите много ресурсов ЦП на транзакции в режиме ядра - подумайте о создании своей собственной (или попытаться найти существующую) гибридную реализацию такой блокировки.