死锁和活锁和饥饿和ReentrantLock

使用多把锁提高并发性

// 一间大屋子有两个功能:睡觉,学习,互不相干
// 现在小南要学习,小女要睡觉,但如果只用一间屋子(一个对象锁)的话,那么并发度很低
// 解决方法是准备多个房间(多个对象锁)
public class Main{
    public static void main(String[] args) {
        BigRoom bigRoom = new BigRoom();
        new Thread(() -> { bigRoom.study(); },"小南").start();
        new Thread(() -> { bigRoom.sleep(); },"小文").start();
    }
}
@Slf4j
class BigRoom {
    private final Object studyRoom = new Object();
    private final Object bedRoom  = new Object();

	// sleep和study业务上没有关联
    public void sleep() throws InterruptedException {
        synchronized (bedRoom){
            log.debug("睡2小时");
            TimeUnit.SECONDS.sleep(2);
        }
    }
    public void study() throws InterruptedException {
        synchronized (studyRoom){
            log.debug("学习1小时");
            TimeUnit.SECONDS.sleep(1);
        }
    }
}

发生死锁

public static void main(String[] args) {
    Object A = new Object();
    Object B = new Object();
    new Thread(() -> {
        synchronized (A) {
            log.debug("lock A");
            synchronized (B) {
                log.debug("lock B");
                log.debug("操作...");
            }
        }
    }, "t1").start();
    new Thread(() -> {
        synchronized (B) {
            log.debug("lock B");
            synchronized (A) {
                log.debug("lock A");
                log.debug("操作...");
            }
        }
    }, "t2").start();
}

定位死锁
使用jstack或者jconosle工具进行定位

# jps查看运行的Java进程
PS C:\Users\hhx> jps -l
10744 jdk.jcmd/sun.tools.jps.Jps
15372 org.jetbrains.jps.cmdline.Launcher
2412 cn.study.Main

# 使用jstack命令
PS C:\Users\hhx> jstack 2412
Found one Java-level deadlock:
=============================
"t1":
  waiting to lock monitor 0x00000217ffa2f400 (object 0x0000000719d5ffe0, a java.lang.Object),
  which is held by "t2"
"t2":
  waiting to lock monitor 0x00000217ffa2fc00 (object 0x0000000719d5ffd0, a java.lang.Object),
  which is held by "t1"

活锁:两个线程都在不断地运行,但是由于互相改变结束条件,导致两个线程结束不了

static volatile int count = 10;
static final Object lock = new Object();
public static void main(String[] args) {
    new Thread(() -> {
        while (count > 0) {
            count--;
            log.debug("count: {}", count);
        }
    }, "t1").start();
    new Thread(() -> {
        while (count < 20) {
            count++;
            log.debug("count: {}", count);
        }
    }, "t2").start();
}

饥饿,有的线程拿到锁的概率太低

public class Singleton{
    public static void main(String[] args) {
        Chopstick c1 = new Chopstick("1");
        Chopstick c2 = new Chopstick("2");
        Chopstick c3 = new Chopstick("3");
        Chopstick c4 = new Chopstick("4");
        Chopstick c5 = new Chopstick("5");
        // 苏和阿要争抢c1(优先级低)
        // 剩下3个,柏拉图c3需要亚,亚c4需要赫,赫的c5被占用概率小
        new Philosopher("苏格拉底", c1, c2).start();
        new Philosopher("柏拉图", c2, c3).start();
        new Philosopher("亚里士多德", c3, c4).start();
        new Philosopher("赫拉克利特", c4, c5).start(); // 执行的机会最多
        new Philosopher("阿基米德", c1, c5).start();
    }
}
@Slf4j
class Philosopher extends Thread {
    private Chopstick left;
    private Chopstick right;
    Philosopher(String name, Chopstick left, Chopstick right) {
        super(name);
        this.left = left;
        this.right = right;
    }
    private void eat() {
        log.debug("eating...");
        try {
            TimeUnit.MILLISECONDS.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    @Override
    public void run() {
        while (true) {
            // 获得左筷子
            synchronized (left) {
                // 获得右筷子
                synchronized (right) {
                    eat();
                }// 放下右筷子
            }// 放下左筷子
        }
    }
}
@ToString
@AllArgsConstructor
class Chopstick {
    String name;
}

ReentrantLock

可中断(避免线程得不到锁一直等待)
可设置超时时间(使用trylock()方法,不会死等)

ReentrantLock lock = new ReentrantLock();
lock.lock();// 获得锁(不可打断,线程得不到锁会一直等待)(lockInterruptibly()可打断)
try{
    // 临界区
} finally {
    lock.unlock();
}

// ReentrantLock支持多间休息室
public static void main(String[] args) {
    ReentrantLock lock = new ReentrantLock();
    Condition condition1 = lock.newCondition();// 创建休息室(相当于waitSet)

    new Thread(() -> {
        lock.lock();// 获得锁
        try{
            // 临界区
            try {
                condition1.await(); // 进入休息室等待,await前需要先获得锁,await会释放锁
                log.debug("醒了======>");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        } finally {
            lock.unlock();
        }
    }).start();

    new Thread(() -> {
        lock.lock();
        try{
            condition1.signal(); // 唤醒condition1休息室中的线程,重新竞争lock锁
            //condition1.signalAll();
        }finally {
            lock.unlock();
        }
    }).start();
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值