首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何解决线程饥饿问题?

如何解决线程饥饿问题?
EN

Stack Overflow用户
提问于 2012-08-18 13:48:15
回答 4查看 12K关注 0票数 4

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

代码语言:javascript
复制
  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仅在循环结束后才会停止获取锁。

代码语言:javascript
复制
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.
EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2012-08-18 14:57:29

ReetrantLock与公平策略一起使用。公平的策略避免线程匮乏。

代码语言:javascript
复制
private final ReentrantLock lock = new ReentrantLock(true);

Java文档

公共ReentrantLock (布尔公平)使用给定的公平策略创建ReentrantLock的实例。参数:

-如果此锁将是公平的,则为true;否则为false

票数 11
EN

Stack Overflow用户

发布于 2012-08-18 14:11:19

我知道你已经有了一个可以接受的答案,但我只想加上我的2美分。

如果您在单核机器上运行,或者甚至是在双核机器上运行,那么问题很可能就是JVM没有足够频繁地交换线程,不足以让另一个线程有机会获得锁。

在任何情况下,只需在释放锁之后调用Thread.yield()就足以让其他线程有机会在原始线程再次获取锁之前获取它。

票数 6
EN

Stack Overflow用户

发布于 2012-08-18 14:44:29

一般来说,锁不应该被长时间持有。所以

代码语言:javascript
复制
        long cookie = data.lock(1);
        Thread.sleep(1000); // Do something.
        data.unlock(1, cookie);

是不可接受的。这样,每个时刻都只有一个线程在“做某件事”。即使您按照建议添加了yeild()或sleep(),吞吐量性能也保持不变。你应该获取锁,获取任务,释放锁,然后才能“做点什么”。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/12016186

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档