我有一个进程a,它在内存中包含一个表和一组记录(recorda、recordb等…)
现在,这个进程可以启动许多影响记录的线程,有时我们会有两个线程试图访问同一个记录-这种情况必须被拒绝。特别是如果一个记录被一个线程锁定,我希望另一个线程中止(我不想阻塞或等待)。
现在我做了这样的事情:
synchronized(record)
{
performOperation(record);
}
但这给我带来了麻烦。。。因为在process1执行操作时,如果process2进入,它将阻塞/等待synchronized语句,并且当process1完成时,它将执行操作。相反,我想要这样的东西:
if (record is locked)
return;
synchronized(record)
{
performOperation(record);
}
关于如何做到这一点有什么线索吗?任何帮助都将不胜感激。谢谢,
7条答案
按热度按时间f0brbegy1#
需要注意的一点是,当你收到这样的信息时,它就过时了。换句话说,可以告诉您没有人拥有锁,但是当您尝试获取它时,会被阻塞,因为另一个线程在检查和您尝试获取它之间取出了锁。
布莱恩说得对
Lock
但我认为你真正想要的是tryLock
方法:你也可以打电话
tryLock
等待的时间很长,因此您可以尝试获取它十分之一秒,如果无法获取它,则中止(例如)。(我认为很遗憾,据我所知,JavaAPI没有为“内置”锁定提供与
Monitor
类在.net中不存在。再说一次,在这两个平台中,当涉及到线程时,还有很多我不喜欢的东西——例如,每个对象都可能有一个监视器!)f4t66c6m2#
看看Java5并发包中引入的锁对象。
例如
reentrantlock对象基本上与传统的
synchronized
机制,但有更多的功能。编辑:正如乔恩所说
isLocked()
方法在那个时刻告诉您,然后该信息就过时了。trylock()方法将提供更可靠的操作(注意,您也可以在超时的情况下使用它)编辑#2:示例现在包括
tryLock()/unlock()
为了清楚起见。pwuypxnk3#
我找到了这个,我们可以用
Thread.holdsLock(Object obj)
要检查对象是否已锁定,请执行以下操作:退货
true
当且仅当当前线程持有指定对象上的监视器锁时。请注意
Thread.holdsLock()
退货false
如果锁被某个东西持有,而调用线程不是持有锁的线程。bkhjykvo4#
虽然上述使用锁定对象的方法是最好的方法,但如果必须能够使用监视器检查锁定,则可以这样做。但是,它确实附带了一个健康警告,因为该技术不能移植到非oraclejavavm上,而且它可能会在将来的vm版本中崩溃,因为它不是一个受支持的公共api。
以下是操作方法:
我的建议是,只有在无法重构代码以使用java.util.concurrent lock对象时,以及在oracle vm上运行时,才使用这种方法。
ux6nzvsh5#
虽然锁的答案是非常好的,我想我会张贴一个替代使用不同的数据结构。基本上,您的各个线程都想知道哪些记录被锁定了,哪些没有。一种方法是跟踪锁定的记录,并确保数据结构具有将记录添加到锁定集的正确原子操作。
我将使用copyonwritearraylist作为一个例子,因为它不太“神奇”。copyonwritearrayset是一种更合适的结构。如果平均在同一时间锁定了很多记录,那么这些实现可能会影响性能。一个正确同步的哈希集也可以工作,并且锁是简短的。
基本上,使用代码如下所示:
它使您不必为每个记录管理一个锁,并提供了一个单独的位置,以确保出于某种原因需要清除所有锁。另一方面,如果您曾经有过多个记录,那么一个真正的具有同步的hashset可能会做得更好,因为add/remove查找将是o(1)而不是线性的。
只是换个Angular 看问题。这取决于实际的线程需求。就我个人而言,我会使用collections.synchronizedset(newhashset()),因为它会非常快。。。唯一的含义是线程可能会屈服,否则它们就不会屈服。
sg24os4d6#
另一个解决方法是(如果你没有机会得到这里给出的答案)使用超时。i、 e.下面的一个将在挂起1秒后返回空值:
iqih9akk7#
谢谢你,它帮助我解决了一个比赛条件。我改了一点,把腰带和吊带都穿了。
因此,我建议对公认的答案进行改进:
你可以确保安全进入
tryLock()
方法如下:这样可以避免你可能会接到两个电话的情况
tryLock()
几乎同时,导致回报率可能被怀疑是充分的。如果我错了,我现在想说,我在这里可能过于谨慎了。但是嘿!我的工作现在稳定了:-)。。在我的博客上阅读更多关于我的发展问题。