这是在Java中创建锁的可接受方式吗?

时间:2013-11-21 19:57:41

标签: java multithreading concurrency

我遇到了这样的逻辑,即有人在今天的工作中实现了,并且以这种方式创建锁是错误的。你们有更好的解决方案吗?不在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
        }
    }
}

8 个答案:

答案 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得到的),使您的设计容易受到死锁,因为您的类的客户端可能获取其实例的锁定并干扰您的自己使用锁。这是使用私有实例作为锁的基本原理。

这是否是您特定代码库中的真正问题是另一回事;它可能只是过度工程。不加批判地遵循“最佳实践”,没有明确的压力。