Иногда могут быть веские причины для реализации ваших собственных блокировок, которые не используют объекты синхронизации ОС Windows. Но это «острая палка». Легко совать себя в ногу.
Вот пример: если вы знаете, что вы используете то же количество потоков, что и аппаратные контексты, и если для вас очень важна задержка пробуждения одного из потоков, ожидающих блокировки, вы можете выберите спин-блокировку, реализованную полностью в пространстве пользователя. Если ожидающий поток является единственным потоком, вращающимся в блокировке, то задержка передачи блокировки из потока, которому она принадлежит, в ожидающий поток - это всего лишь задержка перемещения строки кэша в поток владельца и обратно в ожидающий поток - на несколько порядков быстрее, чем задержка сигнализации потока с блокировкой ОС при тех же обстоятельствах.
Но сценарии, в которых вы хотите это сделать, довольно узки. Как только вы начнете иметь больше программных потоков, чем аппаратных потоков, вы, скорее всего, пожалеете об этом. В этом сценарии вы можете потратить целые кванты планирования ОС, не делая ничего, кроме вращения на вашей спин-блокировке. И, если вы заботитесь о питании, спин-блокировки плохи, потому что они не позволяют процессору переходить в состояние пониженного энергопотребления.
Я не уверен, что куплю аргумент переносимости. Переносимые библиотеки часто имеют уровень переносимости ОС, который абстрагирует различные API-интерфейсы ОС для синхронизации. Если вы имеете дело с блокировками, семантически можно сделать pthread_mutex так же, как Windows Mutex или критический раздел на уровне абстракции. Здесь есть некоторые исключения, но для большинства людей это правда. Если вы имеете дело с переменными условий Windows Events или POSIX, то их сложнее абстрагировать. (В Vista были введены условные переменные в стиле POSIX, но не многие разработчики программного обеспечения для Windows могут требовать Vista ...)