java多线程死锁、强制执行、礼让

本文介绍了Java多线程中出现的死锁问题,包括死锁的必要条件:互斥、请求与保持、不可抢占和循环等待。通过一个四线程、四个资源的例子说明了死锁的循环等待现象。接着,讨论了线程的强制执行,如使用Thread.join()方法,以及线程礼让的概念,虽然礼让不一定成功。最后,概述了线程的四种状态:NEW、RUNNABLE、TIMED_WAITING和TERMINATED。
摘要由CSDN通过智能技术生成

死锁

两个线程分别拿着对方的资源,不释放,形成僵持状态。
下面这个例子,是小花和小白一起化妆,小花先用口红,小白先用镜子,两个人拿到这两样东西后,不给对方,还问对方要对方的东西,形成了僵持状态

public class DeadLock {
public static void main(String[] args) {
	girl g1 = new girl("小花",1);
	girl g2 = new girl("小白",2);
	
	g1.start();
	g2.start();
}
}


class lipstick{
	
}

class mirror{
	
}


class girl extends Thread{
	private static lipstick lipstick = new lipstick();
	private static mirror mirror = new mirror();
	int choice;
	String name;
	
	public girl(String name,int choice) {
		super(name);
		this.choice = choice;
	}

	public void run() {
			makeup();
	}

	public void makeup()
		{
	if(choice == 1) {
		synchronized(lipstick) {
			System.out.println(Thread.currentThread().getName()+"得到了口红锁");
		}
		try {
			Thread.sleep(1000);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		synchronized(mirror) {
			System.out.println(Thread.currentThread().getName()+"得到了镜子锁");
		}
	}else {
		synchronized(mirror) {
			System.out.println(Thread.currentThread().getName()+"得到了镜子锁");
		}
		try {
			Thread.sleep(1000);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		synchronized(lipstick) {
			System.out.println(Thread.currentThread().getName()+"得到了口红锁");
		}
	}
	}
	
}

死锁形成的必要条件:
互斥:某个资源在一段时间内只能由一个线程占有。

请求与保持:进程至少已经占有一个资源,但又申请新的资源;由于该资源已被另外进程占有,此时该进程阻塞;但是,它在等待新资源之时(阻塞状态时),仍继续占用已占有的资源

不可抢占:进程所获得的资源在未使用完毕之前(被锁状态),资源申请者不能强行地从资源占有者手中夺取资源,而只能由该资源的占有者进程自行释放

循环等待:存在一个进程等待序列{P1,P2,…,Pn},其中P1等待P2所占有的某一资源,P2等待P3所占有的某一源,…,而Pn等待P1所占有的的某一资源,形成一个进程循环等待环

四个资源,四个线程:
线程1: 1、2、3、4
线程2: 2、3、4、1
线程3: 3、4、1、2
线程4: 4、1、2、3
线程1、2、3、4同时得到1、2、3、4资源
接下来线程1等线程2,线程2等线程3、线程3等线程4、线程4又等线程1

线程强制执行

Thread.join()方法,线程强制执行 其他线程进入阻塞状态,强制执行线程执行完之后,其他线程再进入就绪状态

//线程强制执行  其他线程进入阻塞状态,强制执行线程执行完之后,其他线程再进入就绪状态
//线程一旦执行完毕,是不可再start()的,因为已经将线程清理出栈区了
public class Testjoin {
public static void main(String[] args) {
	Runnable r = new mRunnable();
	Thread thread1 = new Thread(r,"线程1");
	Thread thread2 = new Thread(r,"线程2");
	
	thread1.start();
	try {
		thread1.join();
	} catch (InterruptedException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	}
	thread2.start();
	
	for(int i = 0;i<=100;i++) {
		System.out.println(Thread.currentThread().getName() +"--"+ i);
	}
}
}

class mRunnable implements Runnable{
    private int i;
	@Override
	public void run() {
		// TODO Auto-generated method stub
		for(i = 0;i<=100;i++) {
			System.out.println(Thread.currentThread().getName() + "--"+i);
		}
	}
	
}

线程礼让

线程礼让:让给其余线程先执行,但不一定礼让成功
礼让后,该线程进入阻塞状态,但很快会再次进入就绪状态

public class Testyield {
	public static void main(String[] args) {
		
		Thread thread = new Thread(()->{
			for(int i = 0;i<=10;i++) {
				System.out.println("副线程:"+i);
			}
			
		});
		
		thread.start();
		System.out.println(thread.getState());
		thread.yield();
		System.out.println(thread.getState());
        try {
			thread.sleep(100);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally {
			System.out.println(thread.getState());
		}
		
		for(int i = 0;i<=10;i++) {
			System.out.println("主线程:"+i);
		}
		System.out.println(Thread.currentThread().getState());
	}
}

运行截图:
在这里插入图片描述

线程的四种状态:
NEW 创建状态
RUNNABLE 运行状态
TIMED_WAITING 阻塞状态
TERMINATED 结束状态

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值