Java 将显式锁与同步方法结合起来

标签 java multithreading concurrency synchronization locking

我有一个线程安全类容器:

public class Container {
  private int x;
  ...
  public synchronized int getX();
  public synchronized void setX(int x);
}

然后我有一个容器列表:

List<Container> containers;

我想遍历列表,在每次迭代时获取容器的锁,并且仅在循环结束时释放所有锁。 像这样:

for(Container c : containers) {
  c.lock();
  //do stuff
}
for(Container c : containers)
  c.unlock();

我仍然希望其他线程能够继续使用已解锁容器的 getX 和 setX 方法,但出于各种原因,我不想对已分析的容器允许这样做。

你知道它的 java 代码吗?

我们也欢迎更好的想法。

最佳答案

这恐怕是不可能的。 Java 语言对 synchronized (...) { ... } block (和同步方法)施加了严格的嵌套原则。

话虽这么说,但还是有一些糟糕的解决方法。在 bytecode 中,同步块(synchronized block)转换为两个单独的 monitorenter/monitorexit 指令。使用 sun.mis.Unsafe.monitorEnter()monitorExit() 也可以达到同样的效果。

但是,在这种情况下,我强烈建议您重新考虑设计。我建议您让 getXsetX 获取/释放内部 Lock (遍历方法也使用)。特别是,您可以使用 ReadWriteLock对于您的 setXgetX 方法。事实上,出于其他原因,这种方法也比使用 synchronized 方法要好。参见示例:

Why is it a good practice to have separate locks instead of having lock on object that get modified in the synchronized block in java?

关于Java 将显式锁与同步方法结合起来,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30798558/

相关文章:

java - Java HornetQ 客户端中的线程处理

android - Glide assert : java. lang.IllegalArgumentException: 你必须在主线程上调用这个方法

c++ - Concurrent_hash_map 实现抛出 SIGSEGV

java - 尝试某些请求时出现 Spring Security 和 Angular 401 错误

java - JDesktopPane 调整大小

java - 检查 IPv4 地址是否有效

python - python线程中的无限循环

java - 如何在 Spring Boot、JPA、Spring Security 中将表单登录扩展到 Google Sign in (OAuth2)

java - 为什么 i++ 不是原子的?

concurrency - CCR:使用因果关系处理错误的最佳实践