Java多线程2.1.多线程之死锁

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/cmm0401/article/details/82711660

多线程之死锁

1、锁对象Lock

虽然我们可以理解同步代码块和同步方法的锁对象问题,但是我们并没有直接看到在哪里加上了锁,在哪里释放了锁。

为了更清晰的表达如何加锁和释放锁,JDK5以后提供了一个新的锁对象Lock。

  • Lock:是一个接口
    • void lock()
    • void unlock()
  • ReentrantLock:Lock接口的一个具体实现类

2、同步弊端:

  • 效率低
  • 如果出现了同步嵌套,就容易产生死锁问题

3、死锁问题及其代码演示:

  • 是指两个或者两个以上的线程在执行的过程中,因争夺资源产生的一种互相等待的现象
  • 同步代码块的嵌套案例

(1)创建线程类

package cn.itcast_02;

public class DieLock extends Thread {

	private boolean flag;

	public DieLock(boolean flag) {
		this.flag = flag;
	}

	@Override
	public void run() {
		if (flag) {
			synchronized (MyLock.objA) {
				System.out.println("if objA");
				synchronized (MyLock.objB) {
					System.out.println("if objB");
				}
			}
		} else {
			synchronized (MyLock.objB) {
				System.out.println("else objB");
				synchronized (MyLock.objA) {
					System.out.println("else objA");
				}
			}
		}
	}
}

(2)创建锁

package cn.itcast_02;

public class MyLock {
	// 创建两把锁对象
	public static final Object objA = new Object();
	public static final Object objB = new Object();
}

(3)测试线程类

package cn.itcast_02;

/*
 * 同步的弊端:
 * 		A:效率低
 * 		B:容易产生死锁
 * 死锁:
 * 		两个或两个以上的线程在争夺资源的过程中,发生的一种相互等待的现象。
 * 举例:
 * 		中国人,美国人吃饭案例。
 * 		正常情况:
 * 			中国人:筷子两支
 * 			美国人:刀和叉
 * 		现在:
 * 			中国人:筷子1支,刀一把
 * 			美国人:筷子1支,叉一把
 */
public class DieLockDemo {
	public static void main(String[] args) {
		DieLock dl1 = new DieLock(true);
		DieLock dl2 = new DieLock(false);

		dl1.start();
		dl2.start();
	}
}

(4)两个线程使用各自的锁,出现了问题:

  • 线程dl1使用锁A输出一句话“if objA”,然后被线程dl2抢去了CPU资源而被迫阻塞;
  • 此时线程dl2使用锁B输出一句话“else objB”,然后又被线程dl1抢去了CPU资源而被迫阻塞;
  • 这时,线程dl1想继续执行下一句话,但是需要锁B,而锁B这时候被线程dl2占用着,所以又被迫阻塞;
  • 这时,如果线程dl2又抢到了CPU资源想继续向下执行的话,但是需要正在被线程dl1占用的锁A,所以又被迫阻塞;
  • 依次产生死锁问题。

猜你喜欢

转载自blog.csdn.net/cmm0401/article/details/82711660