java - 另一个线程进入互斥体

标签 java multithreading thread-safety mutex synchronized

我不明白这段代码有什么问题。有时两个线程开始执行 try block 。每次调用该函数时,我都会创建一个新的 popo 实例。请问有人能弄清楚问题出在哪里吗?

public class Instance {
  private static AtomicInteger i = new AtomicInteger(0);

  public synchronized void incrementInstance() {
    i.getAndIncrement();
  }

  public synchronized void decrementInstance() {
    i.getAndDecrement();
  }

  public synchronized int getInstances() {
    return i.get();
  }
}

public class popo {
  private static volatile MyMutex instanceMutex = new MyMutex();

  public void doSomething() {
    synchronized (instanceMutex) {
      final Instance no = new Instance();
      if (no.getInstances() > 0) {
         instanceMutex.wait();
      } else {
         no.incrementInstance();
      }
    }

    try {
     // do something
    } finally {
        synchronized (instanceMutex) {
          final Instance no = new Instance();
          if (no.Instances() > 0) {
            no.decrementInstance();
          }
          instanceMutex.notify();
        }
     }
  }
  private static class MyMutex {}
}

最佳答案

我认为代码到处都是味道:-)实际上,创建新实例之类的事情只不过是访问静态字段,这会让事情变得困惑(请参阅之前的回复)。所以,这就是我的建议:

  1. 如果您正在编写新代码,则应避免使用等待/通知。查看并发包和《Effective Java》一书中的 Item69。
  2. 根据我对您代码的理解,您需要一个如下信号量:
static final Semaphore SEMAPHORE = new Semaphore(1);
...

SEMAPHORE.take(); // blocks, only one thread is allowed to proceed

try{
   //critical section
} finally {
    SEMAPHORE.release(); // never blocks, always within a finally block
}

然后您可以使用 getQueueLength() 方法来了解有多少线程正在等待并替换您正在使用的 AtomicInteger。请参阅http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/Semaphore.html

  1. 考虑使用执行人。然后,一旦提交了任务,就可以等待Future了。
  2. 如果您仍然想使用 wait/notify,请确保将所有代码放在同步块(synchronized block)中并使用标准习惯用法(Effective Java 中的 Item69):
synchronized(instanceMutex) {
    while(< condition does not hold >) {
        obj.wait();
    }

    // Perform required actions
}

关于java - 另一个线程进入互斥体,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8360301/

相关文章:

sqlite 从事务到保存点的转换

java - 线程间通信问题

java - 由另一个 Thread Java smartcardio 建立的独占访问

c# - IEnumerable Linq 方法是线程安全的吗?

multithreading - Synchronize应该在哪些线程中使用?

java - 连接到 Tomcat 上的 Access 数据库

java - python子进程调用ubuntu 14.04

java - 如何在 JEdit 中编译和运行 java 代码?

c# - 接收并发异步请求并一次处理一个请求

java - 方法/构造函数参数的最终修饰符有什么用