我现在在我的代码中使用ReentrantReadWriteLock来同步对树状结构的访问.这个结构很大,并且很多线程一次读取,偶尔会对它的一小部分进行修改 - 所以它似乎很适合读写习惯用法.我理解,对于这个特定的类,不能将读锁提升到写锁,因此根据Javadoc,必须在获得写锁之前释放读锁.我以前在非重入上下文中成功使用了这种模式.
然而,我发现我无法永久地阻止写入锁定.由于读锁是可重入的,我实际上正在使用它,简单的代码
lock.getReadLock().unlock();
lock.getWriteLock().lock()如果我已经重新获得了重新锁定,则可以阻止.每次解锁调用只会减少保持计数,并且仅在保持计数达到零时才实际释放锁定.
编辑澄清这一点,因为我认为我最初没有解释得太清楚 - 我知道这个类中没有内置的锁升级,我必须简单地释放读锁并获得写锁.我的问题是,无论其他线程正在做什么,如果它重新获取它,调用getReadLock().unlock()可能实际上不会释放此线程对锁定的保持,在这种情况下,调用getWriteLock().lock()将永远阻塞,因为此线程仍然保持读取锁定,从而阻止自己.
例如,即使在没有其他线程访问锁的情况下运行单线程时,此代码段也永远不会到达println语句:
final ReadWriteLock lock = new ReentrantReadWriteLock();
lock.getReadLock().lock();
// In real code we would go call other methods that end up calling back and
// thus locking again
lock.getReadLock().lock();
// Now we do some stuff and realise we need to write so try to escalate the
// lock as per the Javadocs and the above description
lock.getReadLock().unlock(); // Does not actually …我所知道的,writelock就像是同步的.
Readlock和writelock以某种方式相互影响.
ReadLock似乎不能单独工作.
我对多线程环境有些新意,我正在尝试为以下情况提出最佳解决方案:
我每天早上从数据库中读取一次数据,并将数据存储在Singleton对象的HashMap中.我有一个setter方法,只有在发生日内DB更改时才会调用(每天会发生0-2次).
我还有一个getter,它在地图中返回一个元素,这个方法每天被调用数百次.
我担心在我清空和重新创建HashMap时调用getter的情况,因此试图在空/格式错误的列表中找到一个元素.如果我使这些方法同步,它会阻止两个读者同时访问getter,这可能是性能瓶颈.由于写入很少发生,我不想过多地受到性能影响.如果我使用ReentrantReadWriteLock,这会强制任何调用getter的队列,直到释放写锁定为止?是否允许多个读者同时访问getter?它一次只会强制执行一个作者吗?
编码这只是一个问题......
private final ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();
private final Lock read = readWriteLock.readLock();
private final Lock write = readWriteLock.writeLock();
public HashMap getter(String a) {
    read.lock();
    try {
        return myStuff_.get(a);            
    } finally {
        read.unlock();
    }
}
public void setter() 
{
    write.lock();
    try {
        myStuff_ = // my logic
     } finally {
          write.unlock();
    }
}
Java大师,
目前我们有一个经常HashMap<String,SomeApplicationObject>被阅读和偶尔修改的问题,我们遇到的问题是在修改/重新加载期间,Read操作返回null是不可接受的.
要解决这个问题,我有以下选择:
这看起来像是第一选择,但我们所谈论的操作是reload()- 手段clear()紧随其后replaceAll().因此,如果Map是post clear()和pre,replaceAll()则返回null,这是不可取的.即使我synchronize这不解决问题.
B.基于ReentrantReadWriteLock创建另一个实现
在操作Write Lock之前我会在哪里创建获得reload().这似乎更合适,但我觉得必须有一些已经可用的东西,我不需要重新发明轮子.
什么是最好的出路?
编辑任何收藏已经有这样的功能吗?
ReadWriteLockReentrantReadWriteLock实现允许降级(tryLock()从下面的示例总是返回true):
void downgrade(final ReadWriteLock readWriteLock) {
    boolean downgraded = false;
    readWriteLock.writeLock().lock();
    try {
        // Always true, as we already hold a W lock.
        final boolean readLockAcquired = readWriteLock.readLock().tryLock();
        if (readLockAcquired) {
            // Now holding both a R and a W lock.
            assert ((ReentrantReadWriteLock) readWriteLock).getReadHoldCount() == 1;
            assert ((ReentrantReadWriteLock) readWriteLock).getWriteHoldCount() == 1;
            readWriteLock.writeLock().unlock();
            downgraded = true;
            try {
                // Now do some work with only a R lock held
            } finally {
                readWriteLock.readLock().unlock();
                assert ((ReentrantReadWriteLock) …假设我有两个关键资源,foo和bar.我保护他们一些ReentrantReadWriteLocks
ReentrantReadWriteLock foo = new RRWL() ...
ReentrantReadWriteLock bar = new RRWL() ...
大多数操作只使用foo OR bar,但其中一些恰巧使用两者.现在使用单个锁时,您不能只这样做:
void foo() {
   foo.writeLock().lock();
   privateWorkOnFoo();
   foo.writeLock().unlock();
}
如果抛出异常,你的foo将永远被锁定.相反,你把它包起来,就像
void foo() {
    try {
        foo.writeLock().lock();
        privateWorkOnFoo();
    } finally { foo.writeLock().unlock(); }
}
但是,如果我需要同时工作呢?将它们放在一个块中是否安全?
try {
    foo.writeLock().lock();
    bar.writeLock().lock();
    magic();
} finally { 
    bar.writeLock().unlock();
    foo.writeLock().unlock();
}
或者是否有必要为每个锁提供自己的块:
try {
    foo.writeLock().lock();
    try {
        bar.writeLock().lock();
        magic();
    } finally { 
      bar.writeLock().unlock();
    }
} finally { 
    foo.writeLock().unlock();
}
我不可能是第一个很难对此进行调查的人...我知道选项2有"防弹",但它也是一个相当多的维护.选项1是否可以接受?
以下是典型的读写器模式(大量读取和少量写入)
  private ReadWriteLock lock = new ReentrantReadWriteLock();
  private int value;
  public void writeValue(int newValue){
       lock.writeLock().lock();
       try{
           this.value = newValue;
       }
       finally{
           lock.writeLock().unlock();
       }
  }
  public int readValue(){
       lock.readLock().lock();
       try{
           return value;
       }
       finally{
           lock.writeLock().unlock();
       }
  }
我想知道是否有可能优先考虑作家和读者?例如,通常编写者可能会等待很长时间(可能永远),如果其他线程持有读取锁定,那么是否可以让编写器具有更高的优先级,因此每当编写器出现时,它都可以被认为是正如高优先级(跳过线)类似的东西.
java multithreading reentrantreadwritelock readwritelock reentrantlock
在这里搞乱,用循环缓冲区.这是一个明智的实施还是有更快/更可靠的方式来剥皮这只猫?
class CircularBuffer[T](size: Int)(implicit mf: Manifest[T]) {
    private val arr = new scala.collection.mutable.ArrayBuffer[T]()
    private var cursor = 0
    val monitor = new ReentrantReadWriteLock()
    def push(value: T) {
      monitor.writeLock().lock()
      try {
        arr(cursor) = value
        cursor += 1
        cursor %= size
      } finally {
        monitor.writeLock().unlock()
      }
    }
    def getAll: Array[T] = {
      monitor.readLock().lock()
      try {
        val copy = new Array[T](size)
        arr.copyToArray(copy)
        copy
      } finally {
        monitor.readLock().unlock()
      }
    }
  }
请多解释一下合同.我无法弄清楚两个锁是否以ReentrantReadWriteLock某种方式包含在内?或者这些只是一捆两个正常的锁?
我有一些数据结构,我想在其中独占锁定写入访问,但启用并行读取访问。
我进行了一些搜索,找到了类ReadWriteLock和ReentrantReadWriteLock- 它们都提供读锁和写锁。
我不明白它们之间有什么区别。有人可以解释一下吗?