- 2021-11-29
- Views (
1,308 ) - Comments (0)
Java并发编程之3——Java锁的分析
在分析Java的锁之前首先解释一下JVM对的内存分配模型
JVM内存模型
JVM的内存公分为5个部分,主要包括:
- 方法区
- 堆
- 栈
- 程序计数器
- 本地方法栈,
其中方法区和堆是由多线程共享的,其他的区域数据都是由线程独享的,所有在这两个部分保存的数据是所有的线程都可以访问的,我们的锁机制主要也就是保护以下两个方面的内容:
1 保存在堆中的类实例对象(包括实例对象的变量,方法)
2 保存在方法区的类变量
JVM监视器
在java虚拟机上面每个对象和类在逻辑上面都是和一个监视器相关联的,对于对象来说,监视器保护的是对象的实例变量,对于类来说,监视器保护的是类的类变量,为了实现监视器的排他能力,JVM为每个对象分配一个锁(称为内置锁),任何时候只有一个线程可以获得这个锁,当前线程访问实例对象不需要重新获取锁(锁的重入,在后面会介绍), 当只有一个线程获取到该对象的锁之后,在他释放这个锁之前其他线程只能等待。
开发人员不需要加锁,对象锁是java虚拟机自己使用的,以前我一直认为在代码块或者在方法上面加上synchronized关键字就是调用当前对象的内置锁,其实真相是:
当在一个代码块或者方法上加synchronized关键字,就是标示要监视这段代码 (告诉JVM我要监视这段代码,)每当进入被监视的代码块的时候JVM就会自动使用当前对象的内置锁,锁上当前的对象。
对象锁
java中用synchronized监视的代码块获取的锁都是对象的锁,例如:
1 在普通的方法上面添加的锁,就是调用这个方法对应的对象的锁(当这个对象在多个线程之间共享的时候)就会出现线程的同步与互斥
2 在静态方法上面添加锁获取到的是这个类对象的锁
获取同一个对象的锁同时只有一个线程可以执行
|
|
程序的运行结果如下:
|
|
可以看到下面的输出都是两个线程交替输出,原因 : 两个方法拿到的锁都是同一个对象的锁,同一时刻只有一个线程可以拿到这个锁可以执行。
获取不同对象的锁互不影响
|
|
程序的输入如下:
|
|
两个方法可以同时获取到锁,可以同时执行。原因:这两个方法上面使用的锁不是相同的锁,所以他们之间的获取和释放没有任何关系
对象锁和类对象锁
|
|
程序的输入如下:在多线程访问的情况下两个方法可以同时进入,当前对象的锁和类对象的锁不是同一把锁,所以可以同时访问。
|
|
类对象锁的互斥性
|
|
程序的输出如下: 两个方法不会同时执行,都是用的同一个类对象的锁
|
|
本文目录
- No relevant articles
SiteInfo
- TotalArticles:17
- TotalLabels:7
- TotalCategories:4
- TotalComments:0