TReentrantLock(可重入锁)允许效果性地、安全地并发访问某些可变状态,从而允多个纤程读取其中的状态(因为并发读取是安全的),但是只有一个纤程可以修改状态(以防止数据损坏)。此外,TReentrantLock 是使用 STM 实现的,读写操作都可以当作事务进行提交,因此可以将其用作纯 ZIO effect 解决方案的基石,并在内部允许以简单且可组合的方式锁定多个状态(感谢 STM)。 TReentrantLock 是可重入的读/写锁。可重入锁是一个纤程可以多次取得而不会对其自身造成阻塞的锁。在难以跟踪您是否已经获得锁的情况下,此功能很有用。如果锁是不可重入的,则在你获得该锁后再次去获得它时会被阻塞,从而实际上导致了死锁。 语义 该锁对读取方和写入方都提供了重新获得读取或写入锁的重入保证。在释放由写纤程持有的所有写锁之前,不允许读纤程进入。除非没有其他纤程持有写入锁,或者想要写入的纤程已经持有读取锁且没有其他纤程也持有读取锁,否则不允许写纤程进入。 此锁还允许从读锁升级到写锁(自动),以及从写锁降级到读锁(前提是您从读锁升级到写锁是自动的)。 创建一个可重入锁 获取一个读锁 获取一个写锁 多个纤程可同时持有读锁 锁升级和降级 如果您的纤程已经持有读锁,则可以将其升级为写锁,前提是(除了当前纤程外)没有其他读取纤程持有该锁。 在有争议的情况下获取写锁定 只有满足以下条件之一,才能立即获取写锁定: 没有其他的(写入)锁持有人。 当前的纤程已经持有读取锁,且没有其他方持有读取锁。 如果以上两种情况都不满足,则尝试获取写锁定将在语义上阻塞当前纤程。这是一个示例,说明仅当所有其他读取器(尝试获取写锁的纤程除外)释放对(读或写)锁的锁定后,该纤程才能获得写锁。 此例中纤程 f1 获得读取锁定,并在释放它之前休眠 5 秒钟。同时纤程 f2 尝试获取读锁定,并立即尝试获取写锁定。但是,f2 必须在语义上阻塞大约5 秒钟才能获得写锁,因为 f1 到时才将释放其对锁的保留,然后 f2 才能获取写锁定。 更安全的方法(readLock and writeLock) 对于一些简单的使用案例,应避免使用 acquireRead,acquireWrite,releaseRead 和 releaseWrite ,而应该使用诸如 readLock 和 writeLock 之类的方法。借助 Managed 构造,readLock 和 writeLock 可以自动获取并释放锁。下面的程序是一个比上面的例子更安全的版本,它确保一旦通过可重入锁完成操作,我们就不会占用(会释放)任何资源。