SemaphoreSlim основан на SpinWait и Monitor, поэтому поток, ожидающий получения блокировки, в течение некоторого времени сжигает циклы ЦП в надежде получить блокировку до передачи другому потоку. Если этого не происходит, потоки позволяют системам переключать контекст и повторяют попытку (путем сжигания нескольких циклов ЦП), как только ОС снова планирует этот поток. При длительном ожидании этот шаблон может прожигать значительное количество циклов процессора. Таким образом, лучший сценарий для такой реализации - это когда большую часть времени нет времени ожидания, и вы можете почти мгновенно получить блокировку.
Семафор полагается на реализацию в ядре ОС, поэтому каждый раз, когда вы устанавливаете блокировку, вы тратите довольно много циклов ЦП, но после этого поток просто спит столько, сколько необходимо для получения блокировки.