16-其他活跃性问题

nobility 发布于 2021-06-02 1406 次阅读


其他活跃性问题

活锁

当多个线程或进程互相谦让资源,同时主动释放让对方先执行,导致所有进程或线程依然在运行,但程序却得不到进展,因为线程总是重复做释放资源的事情浪费着CPU资源,就是活锁

public class LiveLock {
  public static void main(String[] args) {
    SingleLogBridge singleLogBridge = new SingleLogBridge();
    Pedestrian zhangsan = new Pedestrian("张三");
    zhangsan.setSingleLogBridge(singleLogBridge);
    Pedestrian lisi = new Pedestrian("李四");
    lisi.setSingleLogBridge(singleLogBridge);
    new Thread(() -> {
      lisi.willGo(zhangsan);
    }).start();
    new Thread(() -> {
      zhangsan.willGo(lisi);
    }).start();
  }
}

class SingleLogBridge {
  private Pedestrian pedestrian;  //桥上的人

  public void setPedestrian(Pedestrian pedestrian) {
    this.pedestrian = pedestrian;
  }

  public Pedestrian getPedestrian() {
    return pedestrian;
  }

  public void goBridge() {  //桥上的人过桥
    System.out.println(pedestrian.getName() + "过桥了");
    pedestrian.setGoBridge(true);  //将这个行人状态设置为已过桥
    this.pedestrian = null;  //过完桥,桥上的人清空
  }
}

class Pedestrian {
  private String name;  //行人名字
  private boolean isGoBridge;  //是否过已经过桥
  private SingleLogBridge singleLogBridge;  //桥

  public Pedestrian(String name) {
    this.name = name;
  }

  public String getName() {
    return name;
  }

  public void setGoBridge(boolean goBridge) {
    isGoBridge = goBridge;
  }

  public boolean isGoBridge() {
    return isGoBridge;
  }

  public void setSingleLogBridge(SingleLogBridge singleLogBridge) {
    this.singleLogBridge = singleLogBridge;
  }

  public void willGo(Pedestrian other) {
    while (!this.isGoBridge()) {  //没过桥就要过桥
      if (singleLogBridge.getPedestrian() == null) {  //桥上没人就要上桥
        singleLogBridge.setPedestrian(this);
      }
      if (singleLogBridge.getPedestrian() != this) {  //桥上已经有人,就等待
        try {
          Thread.sleep(100);
        } catch (InterruptedException e) {
          e.printStackTrace();
        }
        continue;
      }
      if (!other.isGoBridge()) {  //对方没过,先让对方过
        System.out.println(name + ":" + other.getName() + "你先过");
        singleLogBridge.setPedestrian(other);
        continue;
      }
      singleLogBridge.goBridge();  //自己过桥
    }
  }
}

解决方案:加入随机因素,一定概率的避让资源,将willGo()方法中的避让代码修改为下面这样(比如以太网指数退避算法)

if (!other.isGoBridge() && new Random().nextBoolean()) {  //50%概率的,若对方没过,先让对方过
  System.out.println(name + ":" + other.getName() + "你先过");
  singleLogBridge.setPedestrian(other);
  continue;
}

饥饿

当线程或进程需要某些资源,但是却始终得不到,比如:

  • 线程优先级设置的过低,导致该线程无法执行陷入饥饿
  • 其他某个线程获得锁陷入无限循环不释放,导致该线程无法执行陷入饥饿
  • 某个程序始终占用某文件的写锁,导致该程序无法执行陷入饥饿

解决方案:不应该设置线程优先级,不应该使用完锁不释放

此作者没有提供个人介绍
最后更新于 2021-06-02