我在单个服务器上实现乐观事务(BOCC)。在提交时,将根据当前数据库状态验证读和写集(如果自读取以来状态已更改,则事务将中止)。如果验证成功,则将所有对象写入数据库。
不同对象集上的验证(加上数据库更新)可以是并发的,但是必须使用读和写锁保护重叠对象集。
我使用ReentrantReadWriteLock来保护验证,这很好。现在,我正在编写一个恢复机制,如果由于某些错误(在验证之后)而不是写入数据库的所有对象,则重复更新过程。
因此,恢复会重复数据库写入,然后尝试释放锁(在恢复成功之后)。问题是,我试图从另一个线程释放锁(因为恢复是由另一个后台服务执行的),这会抛出一个IllegalMonitorStateException。unlock方法上的注释验证了此行为。
/**
* Attempts to release this lock.
*
* <p>If the current thread is the holder of this lock then
* the hold count is decremented. If the hold count is now
* zero then the lock is released. If the current thread is
* not the holder of this lock then {@link
* IllegalMonitorStateException} is thrown.
*
* @throws IllegalMonitorStateException if the current thread does not
* hold this lock
*/
public void unlock() {现在我的问题是:如果需要的话,Java中是否有锁可以使用:
tryLock)?发布于 2015-12-02 10:10:37
StampedLock为我完成了这个任务,可以从另一个线程中解锁。我把它用作:
ReadWriteLock lock = new StampedLock().asReadWriteLock();发布于 2015-12-01 12:23:44
一般来说,将锁从不同的线程释放到声明锁的线程是个坏主意。这样做会引发各种种族状况和其他意想不到的行为。例如,如果最初声明锁的线程由于不知道其他线程已经处理并释放了锁而开始对事物进行更改,会发生什么情况?
相反,向原始线程发送一个信号,说明它已被处理,并让它释放锁。
实际上,tryLock将允许您在不等待的情况下获得一个锁。
如果您只是通过信号来释放锁,那么ReentrantReadWriteLock http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/locks/ReentrantReadWriteLock.html似乎可以做您需要的事情。
您要么需要对原始线程进行重试,要么让原始线程等待(持有锁),直到重试完成,然后自行释放它们。只有声称拥有锁的线程才能释放锁,这几乎是一条普遍的线程规则,因此不会有太多的替代选项。
当然,除非您想要实现自己的锁(例如,在最基本的级别上的AtomicBoolean可以被看作是一个写锁,而AtomicInteger则是一个读锁)。这是一大罐蠕虫,但你可能会打开。正确地进行线程和同步是很困难的。
发布于 2015-12-01 13:21:32
正如@TimB所指出的,一个线程释放(即断开)另一个线程的锁通常是一件危险的事情。
但是,如果您希望在允许的情况下实现自定义锁,则应该能够这样做。如果您查看java.util.concurrent.locks.ReentrantReadWriteLock的实现,例如(这里),Sync.tryReleaseShared(int)实现了释放锁的逻辑。如果您检查它,它实际上正在执行您正在讨论的检查,并在代码中显式抛出异常。虽然我并不认为这是一件简单的事情,但应该可以将这种行为更改为适合您的框架的行为。
我知道现有的“易碎”锁实现吗?不是的。我在GrepCode找不到一个。
为什么?可能是因为其他人怀疑开锁的效用(和安全性)。
https://stackoverflow.com/questions/34019122
复制相似问题