【发布时间】:2020-12-03 22:05:00
【问题描述】:
在 Java 中,假设你有一个数组:
Object[] objs = {o1, o2, ... , oN};
还有一个关键部分:
{
critical();
}
并且您希望在持有 objs 中每个元素的内在锁的同时执行临界区。
我可以想到一种方法来做到这一点,它涉及对递归的可恶滥用:
void syncArray(int i) {
if (i >= 0) {
synchronized(objs[i]) {
syncArray(i - 1);
}
} else {
critical();
}
}
syncArray(objs.length - 1);
除了丑陋之外,这还需要 O(N) 堆栈帧,这可能不是很好。有没有更好的办法?我真正想要的是一种在没有 synchronized 关键字的情况下获取和释放内在锁的方法。如果您以非阻塞方式尝试获取内部锁,则可加分。
注意:我不是在问这是否是一个好主意(不是),只是如果它可能的话。现实世界的答案显然只是使用显式锁,并且对尝试一次为 N 个对象获取锁的智慧进行一些反思。
【问题讨论】:
-
当
i>=4时,假设您可以“展开” 2 或 4 并使用 4 个嵌套的synchronized(objs[i-0..3])块获取 4 个锁。如果递归不只是变成循环,那可能会 JIT 变成不那么糟糕的 asm。 -
您不可以使用
objs作为锁吗? -
所以稍微回答一下我自己的问题:我必须查找是否可以将 monitorenter 和 monitorexit 字节码指令包装在它们自己的函数中,这样它们就可以在不配对的情况下被调用。事实证明,这段代码可能会被 JVM 实现丢弃,因为规范说它是“允许的,但不是必需的”强制执行函数退出时对象的 monitorenter 和 monitorexit 调用的数量必须相同。这意味着我在这个问题中所要求的是不可能的! docs.oracle.com/javase/specs/jvms/se8/html/…
-
虽然这听起来好像你不能将这些指令放在它们自己的函数中,但你能构造一个在循环中发出它们的函数吗?
-
所以您正在考虑是否可以直接使用 Java 字节码,无论您是否可以编写将编译为此类字节码的 Java 源代码? (或通过java-bytecode-asm 库来创建它)。
标签: java locking synchronized monitor locks