在语言级别支持多线程是java语言的一大优势。之前的java并发系列博客中介绍了一些相关的基础知识。这里我们来看看java虚拟机对java多线程的支持。

JVM对多线程的支持有两种:
1 互斥:通过对象锁来实现
2 协同:通过Object类的wait,notify,notifyAll方法来实现


关于互斥:
我们讲过,在JVM的运行时数据区,方法区和堆区是被多有线程共享的,java栈和PC寄存器是线程独占的。因此我们需要考虑多线程访问方法区和堆区时的数据安全问题。 方法区中的共享数据是类变量,堆区的共享数据是对象变量。(不懂看类的生命周期和对象的生命周期相关博客)


Java虚拟机会自动的为每一个类或者对象都关联一个锁,前者叫类锁,后者叫对象锁。可红色部分明明说互斥是通过对象锁来完成的,难道说错了?
这里就需要了解,在jvm中真的是只有对象锁的。逻辑上说的类锁是通过为类的Class对象加锁形成的。在java中,我们常常会使用几种写代码的方式:

第一种 (同步方法)
private synchronized void xxxXxx(){...};
第二种(同步块)
private void xxxXxx(){
synchronized(this){
...}
}
第三种 (静态同步方法)
private static synchronized void xxxXxx(){...};
第四种(静态同步块)
private static void xxxXxx(){
synchronized(A.class){
...}
}
第五种:(私有锁)
private Object myLock=new Object();

上面的第一种形式,当一个类对象a调用xxxXxx方法时,会获得该对象a的对象锁,从而保证方法被同步执行。第二种形式this指代当前方法,因此执行代码块时也会获得a的对象锁。第三种形式,当类A执行他的xxxXxx方法时,会获得类A的类锁,即类A的Class对象的对象锁。第四种形式,当执行代码块的时候,会获得类A的类锁。第五种形式,利用对象myLock的对象锁。

因此,在原理上,第一种和第二种是相同的,第三种和第四种是相同的。

由此可见,在JVM中,锁都是以对象锁的形式存在的。 当JVM在生成对象的时候,会自动的为每一个对象关联一个锁。这就保证了每个对象有对象锁,而每个类有类锁。

关于协作:
JVM对线程协作的支持是通过Object类的wait,notify,notifyAll方法来实现的。
wait方法:使持有当前对象锁的线程释放该对象锁,并进入等待区
notify方法:唤醒一个正在等待当前对象锁的线程
notifyAll方法:唤醒所有正在等待当前对象锁的线程
从对这些方法的功能描述应该容易理解,这些方法必须在同步方法或者同步代码块中被调用。
Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐