对象锁、类锁以及synchronized

原创 2016年08月31日 16:51:17
一、对象锁、类锁
多线程的线程同步机制实际上是靠锁的概念来控制的。
在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会自动释放当前线程占用的锁,因此不会由于异常导致出现死锁现象。

相关文章推荐

Synchronized——的使用(对象锁、类

在进行多线程编程时,Synchronized 基本上都会涉及到,但是一直都是停留在使用的层面,没有系统的了解过,更没有深入的研究过,现在做个简单的整理,有不足的地方,忘大神们多多指教: 类上非...

java synchronized对象锁与类锁的区别、同步代码块与同步方法的区别

终于搞明白synchronized的作用了,献上一篇,如下: java的内置锁:每个java对象都可以用做一个实现同步的锁,这些锁成为内置锁。线程进入同步代码块或方法的时候会自动获得该锁,在退出同步代...

透彻理解 Java synchronized 对象锁和类锁的区别

synchronized 加到 static 方法前面是给class 加锁,即类锁;而synchronized 加到非静态方法前面是给对象上锁。这两者的区别我用代码来演示下: 对象锁和类锁是不同的锁,...

从头认识多线程-2.3 synchronized持有对象锁与类锁的不同点

这一章节我们来讨论游戏,synchronized持有对象锁与类锁的不同点-两种锁是并行的东西,没有交集。1.同步持有对象锁或者类锁package com.ray.deepintothread.ch02...

JAVA多线程之synchronized,对象锁,类锁

JAVA内置锁:java内置锁的两种体现就是对象锁和类锁,java内置锁是一个互斥锁,同时只能被一个线程拿到,线程进入同步方法时自动获取内置锁,退出方法时,释放内置锁。当一个线程A拿到内置锁,其他线程...

从头认识多线程-2.2 synchronized持有对象锁与类锁的相同点

这一章节我们来讨论一下synchronized持有对象锁。1.当所有方法都不使用同步的时候代码清单package com.ray.deepintothread.ch02.topic_2; publi...

java synchronized类锁,对象锁详解

在java编程中,经常需要用到同步,而用得最多的也许是synchronized关键字了,下面看看这个关键字的用法。 因为synchronized关键字涉及到锁的概念,所以先来了解一些相关的锁知识...

Java对象锁和类锁全面解析(多线程synchronized关键字)

最近工作有用到一些多线程的东西,之前吧,有用到synchronized同步块,不过是别人怎么用就跟着用,并没有搞清楚锁的概念。最近也是遇到一些问题,不搞清楚锁的概念,很容易碰壁,甚至有些时候自己连用没...

java synchronized类锁,对象锁详解(转载)

在java编程中,经常需要用到同步,而用得最多的也许是synchronized关键字了,下面看看这个关键字的用法。 因为synchronized关键字涉及到锁的概念,所以先来了解一些相关的锁知识...

java synchronized类锁,对象锁详解(转)

转载自http://zhh9106.iteye.com/blog/2151791 在java编程中,经常需要用到同步,而用得最多的也许是synchronized关键字了,下面看看这个关键字的用法。因...
  • zjf1165
  • zjf1165
  • 2016年08月09日 10:48
  • 331
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:对象锁、类锁以及synchronized
举报原因:
原因补充:

(最多只允许输入30个字)