定义
如果一个线程因为CPU被其他线程全部占有而始终抢不到CPU的运行时间,那么这个线程就是饥饿线程。
实例
由于线程t1的优先级为9,线程t2的优先级为1(最低),造成t2很难抢到CPU的运行时间。
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantReadWriteLock;
public class HungryThread{
ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();
void write(){
readWriteLock.writeLock().lock();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
readWriteLock.writeLock().unlock();
}
void read(){
readWriteLock.readLock().lock();
System.out.println("read");
readWriteLock.readLock().unlock();
}
public static void main(String[] args) {
HungryThread hungryThread = new HungryThread();
Thread t1 = new Thread(()->{
//不停去拿写锁,拿到后sleep一段时间,释放
while (true) {
hungryThread.write();
}
});
Thread t2 = new Thread(()->{
//不停去拿读锁,虽然是读锁,但是...看下面!
while (true){
hungryThread.read();
}
});
t1.setPriority(9);
//优先级低!
t2.setPriority(1);
t1.start();
t2.start();
}
}
解决方案 StampedLock
采用乐观锁机制,判断有没有线程占据锁,没有的话直接执行。
import java.util.concurrent.locks.StampedLock;
public class StampedThread {
StampedLock lock = new StampedLock();
void write(){
long stamp = lock.writeLock();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
lock.unlock(stamp);
}
void read(){
//乐观读
long stamp = lock.tryOptimisticRead();
//判断是否有写在进行,没占用的话,得到执行,打印read
if (lock.validate(stamp)){
System.out.println("read");
}
}
public static void main(String[] args) {
StampedThread stampedThread = new StampedThread();
Thread t1 = new Thread(()->{
while (true) {
stampedThread.write();
}
});
Thread t2 = new Thread(()->{
while (true){
stampedThread.read();
}
});
t1.setPriority(9);
t2.setPriority(1);
t1.start();
t2.start();
}
}
局限性
- StampedLock是不可重入锁。
- StampedLock的悲观读,悲观写锁都不支持条件变量(Condition)