ReentrantReadWriteLock卡在解锁上

如何解决ReentrantReadWriteLock卡在解锁上

我有一个用于获取和释放文件锁的类。我使用的customKey类只是一个带有ID字符串(ID为文件)的reentrantreadwritelock。出于某种原因,这仅在某些情况下有效,并且在大多数情况下,它会挂在所有事物的解锁上-我的调试器跟踪它一直在使用,然后卡住。

我在做什么错?如果线程崩溃并没有释放它的锁,我会得到的,但是这里一个线程尝试调用解锁,并且不再继续。

这是锁定方法

override fun acquire(lockId: String?,ownerId: String?,sequence: Long): Boolean
{
    if (lockId != null)
    {
        lockedList.find { customlock -> customlock.Id == lockId }.apply {
            if (this != null) //lock already exists for this ID
            {
                println("Locking file $lockId Existing lock")
                this.writeLock().lock()
                println("Locked file $lockId")
            } else //lock does not exist
            {
                val newLock = Customlock(lockId)
                lockedList.add(newLock)
                println("Locking file $lockId")
                newLock.writeLock().lock()
                println("Locked file $lockId")
            }
        }
        return true
    } else
    {
        throw InvalidParameterException("ERROR: lockId or ownerId is null!")
    }
}

这是释放方法

override fun release(lockId: String?,ownerId: String?)
    {
        if (lockId != null)
        {
            lockedList.find { customlock -> customlock.Id == lockId }.apply {
                if (this != null)
                {
                    println("Unlocking file $lockId")
                    this.writeLock().unlock()
                    if (this.isWriteLocked)
                    {
                        throw Exception("ERROR: Unlocking Failed!")
                    }
                } else
                {
                    throw Exception("ERROR: Lock not found!")
                }
            }
        }
    }

请不要理会架构,这是由作业决定的。另外,请忽略ownerId和序列变量。

编辑:我尝试只使用一个锁,虽然效率不高,但是确实起作用了,所以@gidds可能在起作用,但是ConcurrentHashMap和ConcurrentLinkedQueue(用List替换更简单)都不能解决问题。 / p>

EDIT2:这是我使用ConcurrentHashMap的新类。它仍然无法正常工作,有人可以指出我的混乱之处吗?谢谢

class LockServer(port: Int) : LockConnector,remoteexception()
{
private val lockedList = ConcurrentHashMap<String,Customlock>()
private var registry: Registry = LocateRegistry.createRegistry(port)

init
{
    registry.bind(ServiceNames.LockService.toString(),UnicastRemoteObject.exportObject(this,port))
}

/**
 * Method acquire() should block the multiple calls from the clients for each specific lockId string.
 * It means when one client acquires the lock "A" and the "A" is not locked by any other clients,* the method should record the lock and return true. If the "A" is already locked by any other client,* the method is blocked and continues only after the lock "A" is released.
 * (Note: Return value false is not used in this basic implementation.
 * Parameters ownerId and sequence are also not used in this basic implementation.)
 */
override fun acquire(lockId: String?,sequence: Long): Boolean
{
    if (lockId != null)
    {
        lockedList.computeIfPresent(lockId){id,value ->
            println("Locking file $id Existing lock")
            value.writeLock().lock()
            println("Locked file $id")
            return@computeIfPresent value
        }
        lockedList.computeIfAbsent(lockId){
            val newLock = Customlock(it)
            println("Locking file $lockId")
            newLock.writeLock().lock()
            println("Locked file $lockId")
            return@computeIfAbsent newLock
        }
        return true
    } else
    {
        throw InvalidParameterException("ERROR: lockId or ownerId is null!")
    }
}

/**
 * Method release() should release the lock and unblock all waiting acquire() calls for the same lock.
 * (Note: Parameter ownerId is not used in this basic implementation.)
 */
override fun release(lockId: String?,ownerId: String?)
{
    if (lockId != null)
    {
        lockedList.computeIfPresent(lockId){ id,value ->
            println("Unlocking file $id")
            value.writeLock().unlock()
            println("Unlocked file $id")
            return@computeIfPresent value
        }
    }
}

/**
 * Method stop() unbinds the current server object from the RMI registry and unexports it.
 */
override fun stop()
{
    registry.unbind(ServiceNames.LockService.toString())
}

}

EDIT3: 获取的新实现:

lockedList.compute(lockId){id,value ->
            if (value == null)
            {
                println("Locking file $id")
                val newLock = Customlock(id)
                newLock.writeLock().lock()
                println("Locked file $id")
                return@compute newLock
            }
            println("Locking file $id Existing lock")
            value.writeLock().lock()
            println("Locked file $id")
            return@compute value
        }

并发布:

println("Unlocking $lockId")
        lockedList[lockId]!!.writeLock().unlock()
        println("Unlocked $lockId")

仍然失败

解决方法

这可能不是您的问题,但是在添加新锁时代码具有竞争条件:如果两个线程尝试锁定同一个(新)文件,则它们都可以为其创建锁。这两个锁都将添加到列表中,但之后只会找到第一个。 (这假定该列表本身是线程安全的;否则,其中一个添加项可能会失败,永久循环或使该列表处于不一致状态,然后崩溃。)

您可以通过一些同步来解决此问题。但是更好的方法可能是将锁存储在ConcurrentHashMap(在锁ID中键入)而不是列表中,并使用原子操作(如computeIfAbsent())安全地创建新锁。 (这也将提高渐近性能,因为它将避免每次扫描列表。)

此外,就样式而言,在锁上使用apply()看起来有些尴尬。 (它通常用于自定义新创建的对象。)我认为let()会更习惯于此。您只需要将this更改为it即可。当然,也可以使用老式的临时变量。

,

这可能不是LockServer类的问题,但是正在使用它的人:

线程1:

Membership.ValidateUser(model.UserName,model.Password)

thread2:

acquire("file1")
acquire("file2")
release("file2")
release("file1")

碰巧执行顺序如下:

acquire("file2")
acquire("file1")
release("file1")
release("file2")

UPD。

考虑对现有锁使用thread1.acquire("file1") thread2.acquire("file2") thread1.acquire("file2") //locked by thread2,waiting thread2.acquire("file1") //locked by thread1... BOOM,deadlock! (可能有些超时)而不是简单的tryLock()

lock()

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?