Java多线程--同步锁ReenTranLock和Condition

1 可中断

public class ReentranLockInterruptibly implements Runnable {

    private static ReentrantLock reentrantLock01 = new ReentrantLock();

    private static ReentrantLock reentrantLock02 = new ReentrantLock();

    private Integer count = 0;

    public ReentranLockInterruptibly(Integer count) {
        this.count = count;
    }

    @Override
    public void run() {
        try {
            if (count == 1) {
                reentrantLock01.lockInterruptibly();
                Thread.sleep(500);
                reentrantLock02.lockInterruptibly();
            } else {
                reentrantLock02.lockInterruptibly();
                Thread.sleep(500);
                reentrantLock01.lockInterruptibly();
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            if (reentrantLock01.isHeldByCurrentThread()) {
                reentrantLock01.unlock();
            }
            if (reentrantLock02.isHeldByCurrentThread()) {
                reentrantLock02.unlock();
            }
            System.out.println(Thread.currentThread().getId() + ":线程退出");
        }
    }

    public static void main(String[] args) throws InterruptedException {
        ReentranLockInterruptibly lockInterruptibly1 = new ReentranLockInterruptibly(
                1);
        ReentranLockInterruptibly lockInterruptibly2 = new ReentranLockInterruptibly(
                2);
        Thread thread01 = new Thread(lockInterruptibly1);
        Thread thread02 = new Thread(lockInterruptibly2);
        thread01.start();
        thread02.start();

        Thread.sleep(1000);
        DeadLockChecker.checkDeadLock();
    }
}

死锁的原因:第一个线程获取reentrantLock01锁,线程被挂起,第二个线程开始获得reentrantLock02锁,第二个线程睡眠,轮到第一个线程开始执行。想获取reentrantLock02锁,但是已经被第二个线程获取了,陷入阻塞状态,等待释放锁资源,轮到第二个线程执行,想要获取reentrantLock01锁,但是发现已经被占用了,陷入了阻塞状态。两个线程都在等待对方释放锁资源,陷入死锁。
解决办法:启动一个守护线程,继承当前各个线程间是否陷入的死锁。
守护线程实现:

public class DeadLockChecker {

    private final static ThreadMXBean mbean = ManagementFactory
            .getThreadMXBean();

    final static Runnable deadLockCheck = new Runnable() {
        @Override
        public void run() {
            while (true) {
                long[] deadLockedThreadIds = mbean.findDeadlockedThreads();
                if (deadLockedThreadIds != null) {
                    ThreadInfo[] threadInfos = mbean
                            .getThreadInfo(deadLockedThreadIds);
                    for (Thread thread : Thread.getAllStackTraces().keySet()) {
                        for (int i = 0; i < threadInfos.length; i++) {
                            if (thread.getId() == threadInfos[i].getThreadId()) {
                                thread.interrupt();
                            }
                        }
                    }
                }
                try {
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }
    };

    public static void checkDeadLock() {
        Thread thread = new Thread(deadLockCheck);
        thread.setDaemon(true);
        thread.start();
    }
}

2 可限时
获取锁资源的限时性,如果一段时间内获取不到锁资源,将会返回

/**
 * 限时获取锁资源
 * 
 * @author Tang 2018年6月30日
 */
public class ReentranLockTimeOut implements Runnable {

    private static ReentrantLock reentrantLock = new ReentrantLock();

    @Override
    public void run() {
        try {
            if (reentrantLock.tryLock(5, TimeUnit.SECONDS)) {
                Thread.sleep(6000);
            } else {
                System.out.println("get lock failed");
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            if(reentrantLock.isHeldByCurrentThread()){
                reentrantLock.unlock();
            }
        }
    }

    public static void main(String[] args) {
        ReentranLockTimeOut reentranLockTime = new ReentranLockTimeOut();
        Thread thread01 = new Thread(reentranLockTime);
        Thread thread02 = new Thread(reentranLockTime);
        thread01.start();
        thread02.start();
    }
}

3 公平锁
构造方法ReentrantLock中一个参数,设置为true,这创建一个公平锁,保证先来的先得,后来的后得。一般情况下是先来的不一定先得,后来的不一定是后得。解决得到锁的不确定性。但是公平锁的性能可能不是蛮好,因为要处理排队的问题。
如下创建一个公平锁:

private static ReentrantLock reentrantLock=new ReentrantLock(true);

4 Condition

public class ReentranLockCondition implements Runnable {

    private static ReentrantLock reentrantLock = new ReentrantLock();

    private static Condition condition = reentrantLock.newCondition();

    @Override
    public void run() {
        try {
            reentrantLock.lock();
            condition.await();
            System.out.println("Thread is going on");
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            if (reentrantLock.isHeldByCurrentThread()) {
                reentrantLock.unlock();
            }
        }
    }

    public static void main(String[] args) throws InterruptedException {
        ReentranLockCondition reentranLockCondition = new ReentranLockCondition();
        Thread thread01 = new Thread(reentranLockCondition);
        thread01.start();

        Thread.sleep(1000);

        // 通知线程继续执行
        reentrantLock.lock();
        condition.signal();
        reentrantLock.unlock();
    }
}

猜你喜欢

转载自blog.csdn.net/BtWangZhi/article/details/80851074