并发之证明偏向锁存在

jdk锁的话synchronize在1.5之前都是重量锁,1.6之后有了偏向锁,轻量锁,重量锁;
重量锁就是每次获取锁都要直接调用操作系统的函数(这里指linux系统)pthread_mutex_lock();
偏向锁是第一次也会调用操作系统函数,之后就不会在调用了;

证明之前先说java线程和os线程的关系;目前来说java和os线程是一一对应的;
当在java中开一个线程的时候,调用start()方法其实是调用了本地的start0()方法,而start0()方法其实是jvm的定义的一个函数如果看jvm的函数源码就能发现它调用了操作系统的pthread_create();java调用其实是依赖了jvm去调用,而java调用jvm就时等于java调用c++的函数,可以通过jni技术,当然jvm不一定是通过这个(这里不做讨论);
当我们java调用start的方法的时候,为什么会直接执行线程里的run()方法呢,可以简单的认为是jvm回调java的run()方法;怎么回调可以百度
(一般通过字节码);
所以启动一个线程其实就是os开了一个线程,接着进入主题,怎么证明偏向锁存在呢?
要证明偏向锁存在的话,就需要知道偏向锁的定义,让我们的锁变成偏向锁,然后让偏向锁的特性显示出来,就可以证明了.
1偏向锁:一个方法里用了synchronize修饰然后启动一个线程无限循环去调用这个方法,因为只有一个线程,不存在资源竞争,所以,这个锁就
变成偏向锁,
2.偏向锁特性:调用一个os的pthread_mutex_lock();之后就不会调用了;
3,偏向锁特性显示出来:要使其特性显示出来,我们可以通过线程的id(os的线程id)来入手,只要证明获取这个方法的锁是该线程的调用的,而且
之后就不会再去调用这个os函数.就可以说明是偏向锁;
证明方案:
1,linux的这些线程函数基本上都在核心库gilbc上,所以我们可以装个linux的虚拟机,然后去网上下载gilbc的源码库替换本地虚拟机的库,当然这个库是我们要在pthread_mutex_lock(); 这个方法里打印出(os的线程id),只要打印出来就说明调用了这个函数;(假设打印:os+“当前线程id”,如os1111)
2,那怎么知道哪个线程id是java的线程呢? 我们可以在这个同步方法里调用一个自定义的native方法,然后在把native方法用c++实现在里面打印os的线程现在执行的线程id(假设打印:java+“当前线程id”,如java1111),(自定义native方法可以用jni技术,可以百度);这样把这个类运行在该linux系统上后,
3,打印的日志是:首先jvm启动时肯定会打印pthread_mutex_lock(); 里的线程id;应为jvm启动时也有自己的线程,也要上锁,然后在控制台可以找到一个线程id和我们java的native方法里打印的线程id是一样的话(假设是11111),就证明这个线程是java线程;
4,应为是一个线程无限循环去拿锁,所以后面只要是这个线程的id:1111,没有在pthread_mutex_lock();这个里面打印只打印java1111说明只调用了一次操作系统的函数,后面就没有调用,所以是偏向锁;

偏向锁膨胀升级
升级主要是有其他竞争这个资源;
假设我们在之前的方法里又启动了一个线程也去调用这个synchronize方法;这时候就是每次线程只要获取锁就要去调用一次pthread_mutex_lock(); 证明方式而上面雷同

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值