java - 重新检查 "synchronized"锁的可变引用?

标签 java multithreading synchronized

我想知道是否有一种简单的方法可以创建一个同步 锁来响应不断变化的引用。我的代码看起来像这样:

private void fus(){
    synchronized(someRef){
        someRef.roh();
    }
}
...
private void dah(){
    someRef = someOtherRef;
}

我希望发生的是:

  1. 线程 A 进入 fus,并在调用 roh() 时获取 someref 上的锁。假设 roh 永远不会终止。
  2. 线程 B 进入 fus,开始等待 someRef` 空闲,并停留在那里(暂时)。
  3. 线程C进入dah,修改someRef
  4. 现在允许线程 B 进入同步块(synchronized block),因为 someRef 不再引用线程 A 锁定的对象。

实际发生的是:

  1. 线程 A 进入 fus,并在调用 roh() 时获取 someref 上的锁。假设 roh 永远不会终止。
  2. 线程 B 进入 fus,找到锁,并等待它被释放(永远)。
  3. 线程C进入dah,修改someRef
  4. 线程 B 继续等待,因为它不再查看 someref,而是查看 A 持有的锁。

有没有办法设置它,以便线程 B 重新检查锁以更改引用,或者将“弹回”到其他代码? (类似 sychronizedOrElse 的东西?)

最佳答案

肯定有办法,但不是synchronized。推理:在第 2 个线程进入 fus() 的时间点,第一个线程持有 someRef 引用的对象的内部锁。重要提示:第​​二个线程仍然会看到 someRef 引用这个对象,并会尝试获取这个锁。稍后,当第 3 个线程更改引用 someRef 时,它必须以某种方式将此事件通知第 2 个线程。这对于 synchronized 是不可能的。

据我所知,没有像synchronized这样的内置语言特性来处理这种同步。

一种稍微不同的方法是管理 Lock在你的类中或者给 someRef 一个 Lock 类型的属性。除了使用 lock(),您还可以使用 tryLock()tryLock(long timeout, TimeUnit unit)。这是我将如何实现它的方案(假设 someRef 有一个 Lock 属性):

volatile SomeRef someRef = ... // important: make this volatile to deny caching
...
private void fus(){
    while (true) {
        SomeRef someRef = this.someRef;
        Lock lock = someRef.lock;
        boolean unlockNecessary = false;
        try {
            if (lock.tryLock(10, TimeUnit.MILLISECONDS)) { // I have chonse this arbritrarily
                unlockNecessary = true;
                someRef.roh();
                return; // Job is done -> return. Remember: finally will still be executed.
                        // Alternatively, break; could be used to exit the loop.
            }
        } catch (InterruptException e) {
            e.printStackTrace();
        } finally {
            if (unlockNecessary) {
                lock.unlock();
            }
        }
    }
}
...
private void dah(){
    someRef = someOtherRef;
}

现在,当 someRef 改变时,第二个线程将在其下一个周期看到 someRef 的新值,因此将尝试在新的 上同步Lock 并成功,如果没有其他线程获得 Lock

关于java - 重新检查 "synchronized"锁的可变引用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37333529/

相关文章:

java - 如何下载文件而不是在浏览器中打开?

java - 使用同步获取意外值

javascript - 如何同步访问 javascript 对象的私有(private)成员

c# - 在主线程中获取 UdpClient 接收数据

c - 使用 C 中的结构将数据传递给 Pthread

java - 使用 CAS 代替同步

java - Hibernate 或 JPA 中的 `SELECT COUNT(*) FROM (SELECT DISTINCT ...)`

java - 如何从字符串中提取未知名称

java - 如何使用 JAVA API 配置我的索引以在 ElasticSearch 中使用 BM25?

node.js - 如何在 Node JS 中执行/中止长时间运行的任务?