java - 如何解决线程饥饿?

标签 java multithreading concurrency

我的类(class)有以下锁定机制。当我运行这个程序时,一个线程不断地获取和重新获取锁,而没有给任何其他线程获取锁的机会,导致饥饿。我如何重构我的锁定机制,以便一旦一个线程放弃一个锁,另一个线程获得它?我希望看到其他线程获取锁,而不必等到拥有锁的线程停止运行。

  private final ReentrantLock lock = new ReentrantLock();
  private final Condition condition = lock.newCondition();

  private final Map<Integer, Long> locksMap = new HashMap<Integer, Long>();

  /** {@inheritDoc} */
  @Override
  public long lock(int recNo) throws RecordNotFoundException {
    ValidationUtils.checkNegative(recNo);

    lock.lock();
    long id = Thread.currentThread().getId();
    try {
      while (locksMap.get(recNo) != null) {
        try {
          System.out.println("Thread " + id + " is waiting.");
          condition.await();
        }
        catch (InterruptedException e) {
          LOGGER.log(Level.SEVERE, e.getMessage());
          return -1;
        }
      }
      Long prevValue = locksMap.put(recNo, id);
      if (prevValue != null) {
        String msg = "Expected no value for " + recNo + " but was ";
        msg += prevValue + ".";
        throw new IllegalStateException(msg);
      }
      System.out.println("Thread " + id + " has the lock.");
    }
    finally {
      lock.unlock();
    }
    return id;
  }

  /** {@inheritDoc} */
  @Override
  public void unlock(int recNo, long cookie) throws RecordNotFoundException, SecurityException {
    ValidationUtils.checkNegative(recNo);
    if (cookie < 0) {
      throw new IllegalArgumentException("cookie is negative.");
    }

    lock.lock();
    try {
      if (locksMap.get(recNo) == cookie) {
        locksMap.remove(recNo);
      }
      else {
        String msg = "Wrong lock cookie. Expected " + locksMap.get(recNo);
         msg += ", was " + cookie + ".";
        throw new IllegalStateException(msg);
      }
      long id = Thread.currentThread().getId();
      System.out.println("Thread " + id + " no longer has the lock.");
      condition.signalAll();
    }
    finally {
      lock.unlock();
    }
  }

  /**
   * Tests the locking mechanism in this class.
   * 
   * @param args None.
   */
  public static void main(String... args) {
    ExecutorService threadPool = Executors.newFixedThreadPool(5);
    final CountDownLatch latch = new CountDownLatch(5);
    final Data data = new Data();
    Runnable task = new Runnable() {
      @Override
      public void run() {
        try {
          for (int index = 0; index < 10; index++) {
            long cookie = data.lock(1);
            Thread.sleep(1000); // Do something.
            data.unlock(1, cookie);
          }
        }
        catch (SecurityException e) {
          e.getStackTrace();
        }
        catch (RecordNotFoundException e) {
          e.getStackTrace();
        }
        catch (InterruptedException e) {
          e.getStackTrace();
        }
        finally {
          latch.countDown();
        }
      }
    };
    for (int index = 0; index < 5; index++) {
      threadPool.execute(task);
    }
    try {
      latch.await();
    }
    catch (InterruptedException e) {
      e.getStackTrace();
    }
    threadPool.shutdown();
  }

这是输出。请注意,只有在循环结束后,线程 9 才会停止获取锁。

Thread 9 has the lock.
Thread 13 is waiting.
Thread 12 is waiting.
Thread 11 is waiting.
Thread 10 is waiting.
Thread 9 no longer has the lock.
Thread 9 has the lock.
Thread 13 is waiting.
Thread 12 is waiting.
Thread 11 is waiting.
Thread 10 is waiting.
Thread 9 no longer has the lock.
Thread 9 has the lock.
Thread 13 is waiting.
Thread 12 is waiting.
Thread 11 is waiting.
Thread 10 is waiting.
Thread 9 no longer has the lock.
Thread 9 has the lock.
Thread 13 is waiting.
Thread 12 is waiting.
Thread 11 is waiting.
Thread 10 is waiting.
Thread 9 no longer has the lock.
Thread 9 has the lock.
Thread 13 is waiting.
Thread 12 is waiting.
Thread 11 is waiting.
Thread 10 is waiting.
Thread 9 no longer has the lock.
Thread 9 has the lock.
Thread 13 is waiting.
Thread 12 is waiting.
Thread 11 is waiting.
Thread 10 is waiting.
Thread 9 no longer has the lock.
Thread 9 has the lock.
Thread 13 is waiting.
Thread 12 is waiting.
Thread 11 is waiting.
Thread 10 is waiting.
Thread 9 no longer has the lock.
Thread 9 has the lock.
Thread 13 is waiting.
Thread 12 is waiting.
Thread 11 is waiting.
Thread 10 is waiting.
Thread 9 no longer has the lock.
Thread 9 has the lock.
Thread 13 is waiting.
Thread 12 is waiting.
Thread 11 is waiting.
Thread 10 is waiting.
Thread 9 no longer has the lock.
Thread 9 has the lock.
Thread 13 is waiting.
Thread 12 is waiting.
Thread 11 is waiting.
Thread 10 is waiting.
Thread 9 no longer has the lock.
Thread 13 has the lock.
Thread 12 is waiting.
Thread 11 is waiting.
Thread 10 is waiting.
Thread 13 no longer has the lock.
Thread 13 has the lock.
Thread 12 is waiting.
Thread 11 is waiting.
Thread 10 is waiting.
Thread 13 no longer has the lock.
Thread 13 has the lock.
Thread 12 is waiting.
Thread 11 is waiting.
Thread 10 is waiting.
Thread 13 no longer has the lock.
Thread 13 has the lock.
Thread 12 is waiting.
Thread 11 is waiting.
Thread 10 is waiting.
Thread 13 no longer has the lock.
Thread 13 has the lock.
Thread 12 is waiting.
Thread 11 is waiting.
Thread 10 is waiting.
Thread 13 no longer has the lock.
Thread 13 has the lock.
Thread 12 is waiting.
Thread 11 is waiting.
Thread 10 is waiting.
Thread 13 no longer has the lock.
Thread 13 has the lock.
Thread 12 is waiting.
Thread 11 is waiting.
Thread 10 is waiting.
Thread 13 no longer has the lock.
Thread 13 has the lock.
Thread 12 is waiting.
Thread 11 is waiting.
Thread 10 is waiting.
Thread 13 no longer has the lock.
Thread 13 has the lock.
Thread 12 is waiting.
Thread 11 is waiting.
Thread 10 is waiting.
Thread 13 no longer has the lock.
Thread 13 has the lock.
Thread 12 is waiting.
Thread 11 is waiting.
Thread 10 is waiting.
Thread 13 no longer has the lock.
Thread 12 has the lock.
Thread 11 is waiting.
Thread 10 is waiting.
Thread 12 no longer has the lock.
Thread 12 has the lock.
Thread 11 is waiting.
Thread 10 is waiting.
Thread 12 no longer has the lock.
Thread 12 has the lock.
Thread 11 is waiting.
Thread 10 is waiting.
Thread 12 no longer has the lock.
Thread 12 has the lock.
Thread 11 is waiting.
Thread 10 is waiting.
Thread 12 no longer has the lock.
Thread 12 has the lock.
Thread 11 is waiting.
Thread 10 is waiting.
Thread 12 no longer has the lock.
Thread 12 has the lock.
Thread 11 is waiting.
Thread 10 is waiting.
Thread 12 no longer has the lock.
Thread 12 has the lock.
Thread 11 is waiting.
Thread 10 is waiting.
Thread 12 no longer has the lock.
Thread 12 has the lock.
Thread 11 is waiting.
Thread 10 is waiting.
Thread 12 no longer has the lock.
Thread 12 has the lock.
Thread 11 is waiting.
Thread 10 is waiting.
Thread 12 no longer has the lock.
Thread 12 has the lock.
Thread 11 is waiting.
Thread 10 is waiting.
Thread 12 no longer has the lock.
Thread 11 has the lock.
Thread 10 is waiting.
Thread 11 no longer has the lock.
Thread 11 has the lock.
Thread 10 is waiting.
Thread 11 no longer has the lock.
Thread 11 has the lock.
Thread 10 is waiting.
Thread 11 no longer has the lock.
Thread 11 has the lock.
Thread 10 is waiting.
Thread 11 no longer has the lock.
Thread 11 has the lock.
Thread 10 is waiting.
Thread 11 no longer has the lock.
Thread 11 has the lock.
Thread 10 is waiting.
Thread 11 no longer has the lock.
Thread 11 has the lock.
Thread 10 is waiting.
Thread 11 no longer has the lock.
Thread 11 has the lock.
Thread 10 is waiting.
Thread 11 no longer has the lock.
Thread 11 has the lock.
Thread 10 is waiting.
Thread 11 no longer has the lock.
Thread 11 has the lock.
Thread 10 is waiting.
Thread 11 no longer has the lock.
Thread 10 has the lock.
Thread 10 no longer has the lock.
Thread 10 has the lock.
Thread 10 no longer has the lock.
Thread 10 has the lock.
Thread 10 no longer has the lock.
Thread 10 has the lock.
Thread 10 no longer has the lock.
Thread 10 has the lock.
Thread 10 no longer has the lock.
Thread 10 has the lock.
Thread 10 no longer has the lock.
Thread 10 has the lock.
Thread 10 no longer has the lock.
Thread 10 has the lock.
Thread 10 no longer has the lock.
Thread 10 has the lock.
Thread 10 no longer has the lock.
Thread 10 has the lock.
Thread 10 no longer has the lock.

最佳答案

使用具有公平策略的ReetrantLock。公平政策避免线程饥饿。

private final ReentrantLock lock = new ReentrantLock(true);

Java 文档

public ReentrantLock(boolean fair) Creates an instance of ReentrantLock with the given fairness policy. Parameters: fair - true if this lock will be fair; else false

关于java - 如何解决线程饥饿?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12016186/

相关文章:

java - 如何使用 return 语句从 Java 中的 for 循环返回多个值?

java - 从 Eclipse 进行单个方法调用,无需类

java - 使用线程上下文ClassLoader从类路径读取WSDL

java - Generic Map<String, Object> 使用 Moxy 进行 JSON 编码和解码

java - 如何处理一组网址而不是每次处理一个网址?

c# - 为什么我的 Winforms 应用程序中的 SynchronizationContext.Current 为空?

代码在没有 volatile 的情况下工作正常?

multithreading - 在 Akka Actors 中阻止调用

mysql - 经典数据库插入问题

java - 如何使用 objectify 确保 Appengine 实体上的并发请求的一致性?