前言:

      关于对象锁,在网上看了很多文章,但都说了不是很清楚。于是查看资料,发现只有从jvm角度讲对象锁才会容易理解。

正文:

     java虚拟机的一些运行时数据区会被所有的线程共享,其他数据时各个线程私有的,因为堆和方法区是被所有线程所共享的,java程序需要为两种多线程访问数据进行协调:

  • 保存在堆中的实例变量
  • 保存在方法区中的类变量

     程序不需要协调保存在java栈中的局部变量,因为java栈中的数据时属于拥有该栈的线程的私有的。

java虚拟机的内部体系结构

线程基础----java对象锁(三)

以下文字摘自《深入java虚拟机》

   在java虚拟机中,每个对象和类在逻辑上都是和一个监视器相关联的。对于对象来说,相关联的监视器保护对象的实例变量,对于类来说,监视器保护类的类变量。如果一个对象没有实例变量。或者一个类没有类变量,相关联的监视器就什么都不监视(补充:变量其实就是数据,加上监视器主要是为了数据安全,一致)。

     为了实现监视器的排他性监视能力,java虚拟机为每个对象和类都关联一个锁(有时候被称为互斥体(mutex))。一个锁就像一种任何时候只允许一个线程“拥有特权”。线程访问实例变量或者类变量就不需要获取锁,但是如果获取了锁,那么他释放这个锁之前,就没有其他线程可以获取同样数据的锁了。(“锁住一个对象”就是获取对象相关联的监视器。)

    类锁实际上用对象锁实现。当java虚拟机转载一个class文件的时候,他会创建一个java.lang.Class类的实例。当锁住一个类的时候,实际上锁住的是那个类的class对象。

    一个线程可以运行多次对同一个对象上锁。对于每一个对象来说,java虚拟机维护一个计数器,记录对象被加了多少次锁。没有被锁的对象计数器为0.但第一个线程第一次获取锁的时候,计数器跳到1,线程每加一次锁一次,计数器就加1.(只有已经拥有了这个对象的锁的线程才能对该对象再次枷锁。在它释放锁之前,其他线程不能对这个对象枷锁)每当线程释放锁一次,计数器就减一。当计数器跳到0的时候,锁就跳到0的时候,锁就被完全释放了,其他线程才可以使用它。

   java虚拟机中的一个线程在它到达监视区域开始处的时候请求一个锁。在java中,有两种监视区域:同步语句和同步方法(这些在本章后面会详细描述)。java程序中的每一个监视区域都和一个对象引用相关联。当一个线程到达监视区域的第一条指令的时候,线程必须对改引用对象枷锁,否则线程不允许执行其中的代码,一旦它获得了锁,线程就进入了被保护的代码。当线程离开这块代码的时候,不管它是如何离开的,它都会释放相关对象的锁。

注意:java编程人员不需要手动枷锁,对象锁是在java虚拟机内部使用的。在java程序中,你只需要编写同步语句,或者同步方法,就可以标示一个监视区域。当java虚拟机运行你的程序的时候,每一次进入一个监视区域的时候,它每次都会自动锁上对象或者类。

转载于:https://my.oschina.net/u/731676/blog/268384

相关文章:

  • 2021-11-30
  • 2022-12-23
  • 2021-11-03
  • 2021-06-30
  • 2021-11-26
  • 2021-10-31
  • 2021-12-14
  • 2021-06-06
猜你喜欢
  • 2021-11-09
  • 2022-03-08
  • 2022-12-23
  • 2021-11-24
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
相关资源
相似解决方案