第三章:java线程重入锁学习「建议收藏」

第三章:java线程重入锁学习「建议收藏」第三章:java线程重入锁学习

大家好,又见面了,我是你们的朋友全栈君。

重入锁,顾名思义,就是支持重进入的锁,它表示该锁能够支持一个线程对资源的重复加锁。重进入是指任意线程在获取到锁之后能够再次获取该锁而不会被锁阻塞,该特性的实现需要解决以下两个问题。

  • 1、线程再次获取锁。锁需要去识别获取锁的线程是否为当前占据锁的线程,如果是,则再次成功获取。
  • 2、锁的最终释放。线程重复n次获取了锁,随后在第n次释放该锁后,其他线程能够获取到该锁。锁的最终释放要求锁对于获取进行计数自增,计数表示当前锁被重复获取的次数,而锁被释放时,计数自减,当计数等于0时表示锁已经成功释放。
  • Java里面内置锁(synchronize)和Lock(ReentrantLock)都是可重入的

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

package com.xiaoyexinxin.ThreadLearn;
/**
 * 锁重入
 *
 */
public class SyncDubbo1 {
	
	public synchronized void method1(final SyncDubbo1 sd){
		System.out.println("线程"+Thread.currentThread().getName()+"进入方法1");
		if(Thread.currentThread().getName().equals("t1")){
			Thread t3=new Thread(new Runnable() {
				
				public void run() {
					// TODO Auto-generated method stub
					sd.method2();
				}
			},"t3");
			t3.start();
		    System.out.println("线程t1的method1方法执行..");  
            method2();  
            System.out.println("线程t1的method1调用结束");  
		} else if(Thread.currentThread().getName().equals("t2")){  
            System.out.println("线程t2的method1方法执行..");  
            method2();  
            System.out.println("线程t2的method1调用结束");  
        }  
	}
	
    public void method2() { 
    	System.out.println("线程"+Thread.currentThread().getName()+"进入方法2");
        if(Thread.currentThread().getName().equals("t1")){  
            System.out.println("线程t1的method2方法执行..");  
            method3();  
            System.out.println("线程t1的method2调用结束");  
        }else if(Thread.currentThread().getName().equals("t2")){  
            System.out.println("线程t2的method2方法执行..");  
            method3();  
            System.out.println("线程t2的method2调用结束");  
        }else if(Thread.currentThread().getName().equals("t3")){  
            System.out.println("线程t3的method2方法执行..");  
            method3();  
            System.out.println("线程t3的method2调用结束");  
        }  
    }  
    public void method3(){  
    	System.out.println("线程"+Thread.currentThread().getName()+"进入方法3");
        if(Thread.currentThread().getName().equals("t1")){  
            System.out.println("线程t1的method3方法执行完毕");  
        }else if(Thread.currentThread().getName().equals("t2")){  
            System.out.println("线程t2的method3方法执行完毕");  
        }else if(Thread.currentThread().getName().equals("t3")){  
            System.out.println("线程t3的method3方法执行完毕");  
        }  
    }  
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		final SyncDubbo1 s=new SyncDubbo1();
		Thread t1=new Thread(new Runnable() {
			
			public void run() {
				// TODO Auto-generated method stub
				s.method1(s);
			}
		},"t1");//t1这个参数是定义线程的名字
		
		Thread t2=new Thread(new Runnable() {
			
			public void run() {
				// TODO Auto-generated method stub
				s.method1(s);
			}
		},"t2");
		
		t1.start();
		t2.start();

	}

}

执行结果:

线程t1进入方法1
线程t1的method1方法执行..
线程t1进入方法2
线程t1的method2方法执行..
线程t1进入方法3
线程t1的method3方法执行完毕
线程t1的method2调用结束
线程t1的method1调用结束
线程t2进入方法1
线程t2的method1方法执行..
线程t3进入方法2
线程t2进入方法2
线程t3的method2方法执行..
线程t2的method2方法执行..
线程t2进入方法3
线程t3进入方法3
线程t2的method3方法执行完毕
线程t2的method2调用结束
线程t2的method1调用结束
线程t3的method3方法执行完毕
线程t3的method2调用结束

   可以看到线程t1和t3执行method2和method3的顺序是不固定的,这样就可能有问题,在处理可能出现线程问题的情况时,我们更希望线程执行的时候不要交叉执行,那么我们可以在method2和method3上加synchronized关键字,

修改后的执行结果是:

线程t1进入方法1
线程t1的method1方法执行..
线程t1进入方法2
线程t1的method2方法执行..
线程t1进入方法3
线程t1的method3方法执行完毕
线程t1的method2调用结束
线程t1的method1调用结束
线程t3进入方法2
线程t3的method2方法执行..
线程t3进入方法3
线程t3的method3方法执行完毕
线程t3的method2调用结束
线程t2进入方法1
线程t2的method1方法执行..
线程t2进入方法2
线程t2的method2方法执行..
线程t2进入方法3
线程t2的method3方法执行完毕
线程t2的method2调用结束
线程t2的method1调用结束

这样就有序执行了。

  可以看到线程t1执行完之后才执行的线程t3,最后执行的是线程t2,线程t1由方法method1要去执行由synchronized修饰的method2,直接便可以获取到锁,这种情况便是锁重入。如果synchronized不支持锁重入的话,会造成死锁的情况(method1还没执行完,要执行method2,method2不让获取锁的话,method1就执行不完了)。

可见重入锁最大的作用是避免死锁

上面说的是一种锁重入的场景,锁重入还有一种常见的情形,那就是父子类的情况,再看一个例子


package com.xiaoyexinxin.ThreadLearn;

public class SyncDubbo2 {
	static class Main{
		int i=10;
		public synchronized void operationed(){
			i--;
			System.out.println("父类i="+i);
			try {
				Thread.sleep(100);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
	static class Sub extends Main{
		public synchronized void operationed(){
			while(i>0){
				i--;
				System.out.println("子类i="+i);
				try {
					Thread.sleep(100);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				super.operationed();
			}
		}
	}

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Thread t1=new Thread(new Runnable() {
			
			public void run() {
				// TODO Auto-generated method stub
				Sub  sub=new Sub();
				sub.operationed();
			}
		});
		t1.start();
	}

}

执行结果:

子类i=9
父类i=8
子类i=7
父类i=6
子类i=5
父类i=4
子类i=3
父类i=2
子类i=1
父类i=0

执行结果如下,可以看到Sub和Main类的方法交替执行,而这两个方法都有synchronized修饰,说明父子类的情况锁重入也是可以的。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/106149.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • python google auth totp_Google Authenticator TOTP原理详解(以Python为例)「建议收藏」

    python google auth totp_Google Authenticator TOTP原理详解(以Python为例)「建议收藏」如果有疑问,请点击此处,然后发表评论交流,作者会及时回复(也可以直接在当前文章评论)。——-谢谢您的参考,如有疑问,欢迎交流一、原理详解(图片可以点击然后放大查看)二、验证1、下载Google谷歌身份验证器。2、通过Python的qrcode和pyotp模块生成二维码。3、然后使用下载的谷歌身份验证器扫描生成的二维码如果没有谷歌服务,则选择输入秘钥,在账户明处填入name参数,在秘…

    2022年10月29日
  • 伊甸园_绿田园农业

    伊甸园_绿田园农业近日,经国务院批复,《全国高标准农田建设规划(2021-2030年)》(以下简称《规划》)正式印发实施。《规划》指出,到2035年,通过持续改造提升,全国高标准农田保有量和质量进一步提高,绿色农田、数字农田建设模式进一步普及,支撑粮食生产和重要农产品供给能力进一步提升,形成更高层次、更有效率、更可持续的国家粮食安全保障基础。《规划》要求利用数字技术,推动农田建设、生产、管护相融合,提高全要素生产效率。重点推进物联网、大数据、移动互联网、智能控制、卫星定位等信息技术在农田建设中的应用,配套耕地质量综合监测点

    2022年10月21日
  • 使用Gson将Object转String出现\u003d 的原因「建议收藏」

    使用Gson将Object转String出现\u003d 的原因「建议收藏」在使用Gson将Object转json字符串,或者将实体类例如:User转为json的过程中,最终的结果会在值中出现\u003d出现这个的原因是Gsongson=newGson()造成的这个时候需要使用Gsongson=newGsonBuilder().disableHtmlEscaping().create();实例化一个gsongson.toJson(…

  • django 视图_基本视图有哪些

    django 视图_基本视图有哪些视图家族drf的视图总共分为以下4个,对应4个源码文件views:视图类generics:工具视图mixins:视图工具集viewsets:视图集学习曲线我们学习视图,可以按照以下的曲线

  • oracle ora-12154问题总结

    oracle ora-12154问题总结在使用oracle时,经常会遇到ora-12154问题,但一直没总结,解决办法过段时间就忘,再遇到问题只能再去找解决办法。今天,把目前了解到的内容汇总记录,方便以后查找。

  • perl正则表达式匹配后的各种变量

    perl正则表达式匹配后的各种变量[root@rwsoda203db1perl_tidb]#catp.pl#!/usr/bin/perlusestrict”subs”;usestrict;usev5.16;my$n=3;my$str=”first.<EM>PARENT</EM>LAST”;$str=~m#(<.*?>)(.*?)(</….

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号