【问题标题】:ReentrantReadWriteLock and synchronized blocksReentrantReadWriteLock 和同步块
【发布时间】:2014-06-08 22:08:51
【问题描述】:

如果我有一个ReentrantReadWriteLock,并且我将它用作同步块中的锁,其他线程还能释放它们的锁吗?

例如:

ReentrantReadWriteLock lock = new ReentrantReadWriteLock(true);

public void doSomething() {
    synchronized(lock) {
        lock.readLock().lock();
        // do stuff
        lock.readLock().unlock();
    }
}

如果我调用doSomething() 并且另一个线程已经持有读锁,那个线程可以释放读锁吗?

当我调用doSomething() 时,我将在ReentrantReadWriteLock 上进行同步,然后尝试获取读锁。由于某些东西已经持有读锁,我将阻塞直到该锁被释放。我很想知道读锁是否可以被释放,因为我已经在锁本身上进行了同步。

【问题讨论】:

  • 呃,既然你一开始就使用锁,为什么还要同步呢?此外,您应该锁定在 try 块前面并在 finally 块中解锁
  • 这是现有代码。我试图找出死锁的根源。我最初认为这是一个哲学家进餐问题,但涉及三个线程。如果由我决定,我什至不会首先包含读/写锁。
  • 我不确定您的确切问题是什么。但是lock.readLock()可以被多个线程获取。关于这段代码......我认为是“过度同步”(如果这个词甚至存在:))并且在我看来使用错误。当你删除同步的块代码时,会发生同样的事情
  • 还有写锁。但我认为在示例中只有一种锁类型会更简单。

标签: java multithreading synchronization locking


【解决方案1】:

在 ReentrantReadWriteLock 对象上进行同步似乎是一个非常糟糕的主意。您的示例是锁定两个完全独立的锁。首先,它锁定每个对象(在本例中为 ReentrantReadWriteLock 对象)内置的互斥锁,然后锁定读锁。

任何时候你看到一个锁,你应该问这个问题,“锁应该保护的不变量是什么?”这是另一种提问方式,“如果没有锁,你的数据会以什么方式被破坏?”

好的,synchronized(lock) 保护什么?

还有,lock.readLock().lock() 保护什么?

如果两个答案都相同,那为什么要使用两个锁呢?

如果由我决定,我什至不会一开始就包括读/写锁

你不妨把你的例子改成这样:

Object lock = new Object();

public void doSomething() {
    synchronized(lock) {
        // do stuff
}

就您向我们展示的代码而言,它的行为不会有任何不同。 (不过,它可能会改变您的示例与您未向我们展示的其他代码交互的方式。)

【讨论】:

    【解决方案2】:

    写一个例子来说明一个线程持有实际锁对象上的监视器并不妨碍其他线程获取和释放读锁,这是相当简单的。 (这当然没有实际记录,因此理论上对于替代 Java 实现可能会有所不同!)

    public static void main(String[] args) throws Exception {
        final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(true);
    
        synchronized (lock) {
            lock.readLock().lock();
            try {
                for (int i = 0; i < 10; i++) {
                    new Thread(new Runnable() {
                        @Override
                        public void run() {
                            lock.readLock().lock();
                            try {
                                System.out.println("foo");
                            } finally {
                                lock.readLock().unlock();
                            }
                        }
                    }).start();
                }
                Thread.sleep(500);
                System.out.println("done");
            } finally {
                lock.readLock().unlock();
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-12-10
      • 2011-07-14
      • 1970-01-01
      相关资源
      最近更新 更多