java并发编程实战笔记-死锁

死锁的定义:

按书上所说,死锁就是自己拥有其他人需要的资源,同时又在等待其他人已经拥有的资源,并且每个人在获得所需要的资源之前都不会放弃自己已经有的资源。

死锁的类型:

1.简单的顺序死锁:
public class die1 {

	public Object lock1 = new Object();
	public Object lock2 = new Object();


	public void die1Mthod1(){
		synchronized(lock1){
			synchronized(lock2){


			}
		}
	}

	public void die1Mthod2(){
		synchronized(lock2){
			synchronized(lock1){


			}
		}
	}
}
对于上线的类,如果只有一个线程串行执行的话,绝对不会发生死锁,但是如果超过两个线程,并且等待时间足够长,那么当一个线程在执行方法一同时另一个线程在执行方法2的时候就会出现死锁。因为两个线程持有对方需要的资源,程序会暂停执行,发生死锁。

2.动态的死锁:
public class die2 {

	public static Object fromAccount = new Object();
	public static Object toAccount = new Object();

	public static void transfer(Object fromAccout,Object toAccount,int money) throws InterruptedException{

		/*if(fromAccout.hashCode() < toAccount.hashCode()){
			Thread.sleep(3000);
			synchronized(fromAccout){
				synchronized(toAccount){
					System.out.println(Thread.currentThread().getName() + "交易金额+:" + money); 
				}
			}
		}
		if(fromAccout.hashCode() > toAccount.hashCode()){
			Thread.sleep(3000);
			synchronized(toAccount){
				synchronized(fromAccout){
					System.out.println(Thread.currentThread().getName() + "交易金额! :" + money); 
				}
			}
		}*/
		/*	未定义之前的锁顺序	
		 */
		//Thread.sleep(3000);
		synchronized(fromAccout){
			Thread.sleep(1000);    (1)
			synchronized(toAccount){
				System.out.println("交易金额:" + money); 
			}
		}
	}


	public static void main(String[] args){
		Thread thead1 = new Thread(new Runnable(){

			@Override
			public void run() {
				try {
					die2.transfer(die2.fromAccount, die2.toAccount, 500);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}

		});

		Thread thead2 = new Thread(new Runnable(){

			@Override
			public void run() {
				try {
					die2.transfer(die2.toAccount, die2.fromAccount, 100);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}

		});
		
		
		
		
		thead2.start();
		thead1.start();
		
	}
}
上面所示,在一处是为了让线程一在获得了fromAccount这个锁后,延迟获得toAccount锁,让线程2获得,这样就能产生死锁,所以这样的代码虽然避免了死锁1的情况,但是会在程序运行的时候因为参数的原因导致了死锁。注释部分为解决方法。

3.协作对象的死锁:
public class die3 {

	static class die33{
		public static synchronized void method11() throws InterruptedException{
			//Thread.sleep(1000);
			method1();
			System.out.println("method11");
		}

		public static synchronized void method22(){
			System.out.println("method22");
		}
	}


	//注意:没有休眠,不会死锁,但是会引起栈的溢出
	public static synchronized void method1(){	
		System.out.println("method1");
	}

	public static synchronized void method2() throws InterruptedException{
		//Thread.sleep(1000);
		die33.method22();
		System.out.println("method2");
	}


	public static void main(String[] args){
		Thread thead1 = new Thread(new Runnable(){

			@Override
			public void run() {
				try {
					die3.method2();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}

		});

		Thread thead2 = new Thread(new Runnable(){

			@Override
			public void run() {
				try {
					die3.die33.method11();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}

		});




		thead2.start();
		thead1.start();
	}
}
因为虽然没有锁的顺序,但是在调用方法上,两个线程有可能会持有,两个不同的对象的锁,而有等待对方的锁,从而产生死锁。

解决死锁的办法:

1)接触顺序死锁的关系:如果die2的注释。
2)开放调用:在die3中,使用synchronized(this){}用于保护仅需要同步的操作,减少持有锁的时间。
3)使用定时锁,一定时间不能获得锁(tryLock),那么他将会放弃。

其他危险:

1)避免使用线程(api)的优先级,那会增加对平台的依赖,不正确的优先级,导致一些线程得不到cpu时间片,导致饥饿,所以使用java默认优先级。
2)线程重复执行相同的操作,而且总会失败,导致虽然没有阻塞进程,但是程序仍然没有执行,例如,两台机器同时发出消息,都发现了冲突,那么为失败,但是它们又会都等待相同的时间,从而导致程序一直失败的执行下去,所以可以让他们等待随机的时间,或者回退即可解决这样的活锁。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值