并发编程:锁重入与锁异常

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了并发编程:锁重入与锁异常相关的知识,希望对你有一定的参考价值。

1、synchronized重入

 关键字synchronized拥有锁重入的功能,也就是在使用synchronized时,当一个线程得到了一个对象的锁后,再次请求此对象时是可以再次得到该对象的锁。


1.1 同步方法间的调用

public class Demo5 {
	public synchronized void method1() throws InterruptedException {
		System.out.println("method...");
		method2();
		Thread.sleep(2000);
	}
	
	public synchronized void method2() throws InterruptedException {
		System.out.println("method2...");
		method3();
		Thread.sleep(2000);
	}
	
	public synchronized void method3() throws InterruptedException {
		System.out.println("method3...");
		Thread.sleep(2000);
	}
	
	public static void main(String[] args) {
		final Demo5 demo5 = new Demo5();
		Thread t1 = new Thread(new Runnable() {
			@Override
			public void run() {
				try {
					demo5.method1();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		});
		t1.start();
	}
}


效果:

    技术分享

此处无须等待method1释放锁,method2、method3亦可执行。


1.2 父子同步方法的调用

public class Demo5_2 {
	static class Main {
		public int i = 10;
		public synchronized void operationSup(){
			try {
				i--;
				System.out.println("父 print i = " + i);
				Thread.sleep(100);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
	static class Sub extends Main {
		public synchronized void operationSub(){
			try {
				while(i > 0) {
					i--;
					System.out.println("子 print i = " + i);
					Thread.sleep(100);		
					this.operationSup();
				}
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
	
	public static void main(String[] args) {
		Thread t1 = new Thread(new Runnable() {
			@Override
			public void run() {
				Sub sub = new Sub();
				sub.operationSub();
			}
		});
		t1.start();
	}
}

效果:

    技术分享

2、锁异常

 出现异常,锁会自动释放

 对于web应用程序,异常释放锁的情况,如果不及时处理,很可能对应用程序业务逻辑产生严重的错误,比如现在执行一个队列任务,很多对象都去在等待第一个对象正确执行完毕再去释放锁,但是第一个对象由于异常的出现,导致业务逻辑没有正常执行完毕,就释放了锁,那么可想而知后续的对象执行的都是错误的逻辑。所以一定要引起注意,在编写代码的时候,一定要考虑周全。


public class Demo6 {
    private int i = 0;
    public synchronized void method() {
        while(true) {
            try {
		i++;
		Thread.sleep(200);
		System.out.println(Thread.currentThread().getName() + " , i = " + i);
		if (i == 3) {
		    Integer.parseInt("a");
		    // throw new RuntimeException();
		}
	    } catch (Exception e) { // InterruptedException
		e.printStackTrace();
		System.out.println(" log info i = " + i);
		//throw new RuntimeException();
		//continue;
	    }
	}
    }
	
    public static void main(String[] args) {
	final Demo6 demo6 = new Demo6();
	Thread t1 = new Thread(new Runnable() {
	    @Override
	    public void run() {
		demo6.method();
	    }
	}, "t1");
	t1.start();
    }
}


效果:技术分享


说明:当i=3的时候,Integer.parseInt("a");出现异常了,但是后续还在执行,这并不是我们想要的结果。


解决思路:

  第一种:在异常块里记录日志

  第二种:抛出运行时异常,throw new RuntimeException();

  第三种:打断InterruptedException



效果:第二种

技术分享

效果:第三种与第二种一样

本文出自 “我爱大金子” 博客,请务必保留此出处http://1754966750.blog.51cto.com/7455444/1905537

以上是关于并发编程:锁重入与锁异常的主要内容,如果未能解决你的问题,请参考以下文章

java多线程编程核心技术——第二章总结

Java并发编程之重入锁与读写锁

共享锁排他锁重入锁锁的公平与非公平

深入理解Java中的synchronized锁重入

Java Thread系列synchronized

可重入与线程安全