对象锁、类锁以及synchronized

一、对象锁、类锁
多线程的线程同步机制实际上是靠锁的概念来控制的。
在Java程序运行时环境中,JVM需要对两类线程共享的数据进行协调:
1)保存在堆中的实例变量
2)保存在方法区中的类变量
注:程序不需要协调保存在Java 栈当中的数据。因为这些数据是属于拥有该栈的线程所私有的。

在java虚拟机中,每个对象和类在逻辑上都是和一个监视器相关联的。
对于对象来说,相关联的监视器保护对象的实例变量。对于类来说,监视器保护类的类变量。

为了实现监视器的排他性监视能力,java虚拟机为每一个对象和类都关联一个锁,代表任何时候只允许一个线程拥有的特权。锁住一个对象或类就是获取相关联的监视器,其它线程只能等了(线程阻塞在锁池等待队列中)。
注:线程访问实例变量或者类变量不需锁。
类锁实际上用对象锁来实现。当虚拟机装载一个class文件的时候,它就会创建一个java.lang.Class类的实例。当锁住一个对象的时候,实际上锁住的是那个类的Class对象。

一个线程可以多次对同一个对象上锁。对于每一个对象,java虚拟机维护一个加锁计数器,线程每获得一次该对象,计数器就加1,每释放一次,计数器就减 1,当计数器值为0时,锁就被完全释放了。
在java程序中,只需要使用synchronized块或者synchronized方法就可以标志一个监视区域。当每次进入一个监视区域时,java 虚拟机都会自动锁上对象或者类。编程人员不需要自己动手加锁,对象锁是java虚拟机内部使用的。

二、synchronized
Java语法规定,任何线程执行同步方法、同步代码块之前,必须先获取对应的监视器(每个对象都有一个锁标记,每个类也都有一个锁标记)。

1.
private synchronized void testSyncMethod() {          //监视器是调用本方法的引用对象
}
当一个对象P1在不同的线程中执行这个同步方法时,他们之间会形成互斥,达到同步的效果。
但是这个对象所属的Class所产生的另一对象P2却能够任意调用这个被加了synchronized关键字的方法,对P2而言,P1这个锁和它毫不相干。
等同于下边第二种的写法。

2.
private void testSyncBlock() {     //监视器是this,即调用该方法的引用对象
     synchronized (this) {
     }
}

3.
private static synchronized void testSyncMethod() {          //加了static关键字,故它的监视器是该类本身
}
如果一个线程执行一个对象的非static synchronized方法,另外一个线程需要执行这个对象所属类的static synchronized方法,此时不会发生互斥现象,因为访问static synchronized方法占用的是类锁,而访问非static synchronized方法占用的是对象锁,所以不存在互斥现象。

4.
private void testSyncBlock() {          //监视器是该类本身
     synchronized (RunnableTest.class) {
     }
}

5.
public void method(SomeObject so) {
     synchronized(so){
     }
}
这时,锁就是so这个对象,谁拿到这个锁谁就能够运行他所控制的那段代码。


当有一个明确的对象作为锁时,就能够这样写程式,但当没有明确的对象作为锁,只是想让一段代码同步时,
能够创建一个特别的instance变量(它得是个对象)来充当锁:
class Foo implements Runnable
{
     private byte[] lock = new byte[0];
     public void method() {
          synchronized(lock) {
          }
     }
}
注:零长度的byte数组对象创建起来将比任何对象都经济。
查看编译后的字节码:生成零长度的byte[]对象只需3条操作码,而Object lock = new Object()则需要7行操作码。

另:
对于synchronized方法或者synchronized代码块,当出现异常时,JVM会自动释放当前线程占用的锁,因此不会由于异常导致出现死锁现象。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值