2015-04-18 3 views
0

Рассмотрите график социальной сети с пользователями и новостями. Существует несколько методов, которые изменяют график, и их можно вызывать одновременно.
Я реализовал менеджер блокировки, чтобы избежать любых мертвых замков. Он блокирует пользователей, заказанных с самого низкого идентификатора пользователя, который хранится как свойство в пользовательских узлах. Замки выпускаются в обратном порядке.Блокировка освобождает причины мертвой блокировки в Neo4j

Тем не менее я получаю следующее DeadLockDetectedException при выполнении определенного метода одновременно:

[email protected]: 
    locking manager locked [NODE(0) [#1], NODE(5) [#3]] 
[email protected]: 
    locking manager released [NODE(5) [#3], NODE(0) [#1]] 
[email protected]: 
    locking manager locked [NODE(1) [#2] 
Exception in thread "Thread-3" [email protected]: 
    org...DeadlockDetectedException: 
    LockClient[18] can't wait on resource RWLock[NODE(1)] since => 
    LockClient[18] <-[:HELD_BY]- RWLock[NODE(5)] <-[:WAITING_FOR]- LockClient[20] <-[:HELD_BY]- RWLock[NODE(1)] 
[email protected]: 
    locking manager locked [NODE(1) [#2], NODE(5) [#3]] 

Как вы можете видеть, транзакция блокирует два узла пользователя (ID 1 и 3). Чуть позже он пытается заблокировать другой пользовательский узел (id 2), но эта блокировка не может быть получена: есть вторая транзакция, которая заблокировала пользователя с идентификатором 2 и ждет, чтобы заблокировать пользователя с идентификатором 3.
Правдоподобно, это был бы мертвый замок.

Однако код и предыдущее сообщение в журнале сообщают другую историю: Прежде чем транзакция попытается заблокировать пользователя с идентификатором 2, он освободил два блокировки, которые он приобрел ранее. Вот соответствующий код:

Transaction tx = graph.beginTransaction(); 
    // locks NODE(0) and NODE(5) 
Lock[] locks = LockManager.lock(tx, following, followed); 
boolean result = removeFollowship(following, followed); 
    // releases NODE(5) and NODE(0) 
LockManager.releaseLocks(locks); 
... 
    // tries to lock NODE(1) 
List<Lock> locks = LockManager.lock(tx, replicaLayer); 
try { 
    return addStatusUpdate(author, statusUpdate); 
} finally { 
    LockManager.releaseLocks(locks); 
} 
... 
tx.success(); 

Менеджер блокировки замков узлов через tx.acquireWriteLock(node) и высвобождает замков через lock.release().
Есть ли что-нибудь, о чем я не знаю? Например, существует ли задержка между вызовом lock.release и новой блокировкой соответствующего узла?

ответ

1

Замки действительно просто выпущены, когда сделка заканчивается.

Именно поэтому до тех пор, пока ваш tx.close() не назван, он все еще удерживает замки.

+1

http://neo4j.com/docs/stable/javadocs/org/neo4j/graphdb/Lock.html: "' release() 'Освобождает эту блокировку до завершения транзакции. Это необязательная операция, и если ее не вызывать , этот замок будет освобожден, когда сделка с владельцем закончится ». Я понимаю что-то другое, и если вы правы, каким будет использование этого метода? –

Смежные вопросы