Чтобы понять это в деталях, вам нужно пройти курс обучения операционной системе (или, по крайней мере, купить хорошую книгу по этому предмету), потому что на самом деле это довольно много систем.
Однако в основном это относится к управлению состоянием потока. Поток - это одно из нескольких разных состояний одновременно: спящий, готовый или работающий (обычно это больше, но это все, что нужно для целей этого обсуждения). Поток в рабочем состоянии на самом деле работает, и код в потоке выполняется. Поток в «спящем» состоянии не запущен, и планировщик пропустит его, когда решит, кто будет работать дальше. Поток в состоянии «готовности» в данный момент не выполняется, но как только другой поток переходит в спящий режим или его временной интервал истекает, планировщик может свободно планировать переход этого потока в состояние выполнения.
Таким образом, в основном, когда вы вызываете «wait» для объекта мьютекса, ОС проверяет, принадлежит ли объект уже другому потоку, и если да, устанавливает состояние текущего потока как «спящий», а также помечает поток как «ожидающий» на "этот конкретный мьютекс.
Когда поток, которому принадлежит мьютекс, завершен, ОС перебирает все ожидающие его потоки и устанавливает их в состояние «готов». В следующий раз, когда планировщик приходит в себя, он видит «готовый» поток и переводит его в «работающее» состояние. Поток запускается и проверяет, может ли он снова получить блокировку мьютекса. На этот раз никто не владеет им, поэтому он может продолжать свой веселый путь.
На самом деле, это намного сложнее, и много усилий направлено на то, чтобы сделать систему максимально эффективной (например, чтобы не пробуждать поток, а просто немедленно вернуть его в спящий режим, чтобы избежать поток, умирающий от мьютекса, который ожидает множество других потоков и т. д. и т. д.)