Блокировки могут обеспечивать взаимное исключение, но не синхронизацию условий. В отличие от семафора, у блокировки есть владелец, и владение играет важную роль.
роль в поведении замка
пример -
class lockableObject { public void F() {
mutex.lock(); ...; mutex.unlock();
}
public void G() {
mutex.lock(); ...; F(); ...; mutex.unlock();
}
private mutexLock mutex; }
// method G() calls method F()
Блокировка мьютекса в классе lockableObject используется для превращения методов F () и G () в критические секции. Таким образом, только один поток одновременно может выполняться внутри метода lockableObject. Когда поток вызывает метод G (), мьютекс блокируется. Когда метод G () вызывает метод F (), mutex.lock () выполняется в F (), но вызывающий поток не блокируется, поскольку он уже владеет мьютексом. Если бы мьютекс был двоичным семафором, а не блокировкой, вызов из G () в F () заблокировал бы вызывающий поток, когда mutex.P () был выполнен в F (). (Напомним, что завершение операций P () и V () на двоичном семафоре должно чередоваться.) Это создаст тупик, поскольку никакие другие потоки не смогут выполняться внутри F () или G ().
Это различия между замками и двоичными семафорами:
1 Для двоичного семафора, если два вызова сделаны toP () без какого-либо промежуточного вызова V (), второй вызов заблокируется. Но поток, который владеет блокировкой и снова запрашивает владение, не блокируется. (Остерегайтесь того факта, что блокировки не всегда рекурсивны, поэтому проверьте документацию перед использованием блокировки.)
2 Владелец для последовательных вызовов lock () и unlock () должен быть одним и тем же потоком. Но последовательные вызовы P () и V () могут выполняться разными потоками.