我遇到了这样的逻辑,即有人在今天的工作中实现了,并且以这种方式创建锁是错误的。你们有更好的解决方案吗?不在myObj上使用synchronized块的问题是它可以为null。还有其他建议吗?
public class myClass {
private Object myObj;
private Object lock = new Object();
public void method1() {
synchronized( lock ) {
// has logic to read myObj
}
}
public void method2() {
synchronized( lock ) {
// has logic to update myObj
}
}
}
答案 0 :(得分:10)
看起来适合我。我还要将final
添加到锁定声明中,以确保它不会无意中被更改:
private final Object lock = new Object();
答案 1 :(得分:3)
这是合适的。另一种方法是,如果你想要锁定,那么同步this
是一个热烈的争论。
答案 2 :(得分:1)
我想你可以final
你的lock
字段。但是我认为你的做法很好。
答案 3 :(得分:1)
我认为这是可以接受的。 Pre-Java 1.5我认为没有替代品。现在您可能更喜欢使用Lock
的一种实现方式。
答案 4 :(得分:1)
实例字段lock
应标记为final(这样我们可以确保引用的对象永远不会更改)。除此之外,它是合适的。考虑使用ReentrantReadWriteLock,这样可以让您拥有几乎无限量的并发读者。对于synchronized
,除了一个之外的所有线程都将独立于其操作类型进行阻塞。
如果method1和method2是myClass上声明的唯一方法,那么您可以在方法声明中交换synchronized块和关键字synchronized的lock变量。隐式地,执行线程将尝试获得与调用的类实例相关联的监视器的所有权。
以下是使用ReentrantReadWriteLock
的类的一个版本,它将允许并发读者(同样,写锁可以“降级”以读取锁定,而不是相反):
import java.util.concurrent.locks.ReentrantReadWriteLock;
public class MyClass
{
private Object myObject;
private final ReentrantReadWriteLock myObjectLock = new ReentrantReadWriteLock();
public void readMyObject()
{
ReentrantReadWriteLock.ReadLock r = myObjectLock.readLock();
r.lock();
try {
; // Read myObject.
}
finally {
r.unlock();
}
}
public void writeMyObject()
{
ReentrantReadWriteLock.WriteLock w = myObjectLock.writeLock();
w.lock();
try {
; // Write myObject.
}
finally {
w.unlock();
}
}
}
答案 5 :(得分:0)
我认为创造这样的锁定不应该感觉不对!这只是在java中制作锁的正确方法!
答案 6 :(得分:0)
您可以使用ReentrantLock。与同步相比,这更快,更灵活。有关详细信息,请参阅此documentation。
答案 7 :(得分:0)
在this
上进行同步(这是通过简单地标记方法synchronized
得到的),使您的设计容易受到死锁,因为您的类的客户端可能获取其实例的锁定并干扰您的自己使用锁。这是使用私有实例作为锁的基本原理。
这是否是您特定代码库中的真正问题是另一回事;它可能只是过度工程。不加批判地遵循“最佳实践”,没有明确的压力。