synchronized关键字解析(和lock区别)

一、syschronized底层实现原理

  首先Java中基本的互斥同步手段就是syschronized关键字。在JVM中,每个对象和类在逻辑上都是和一个监视器相关联的,JVM为每一个对象和类都关联一个锁 锁住了一个对象,就是获得对象相关联的监视器。
  syschronized关键字在经过编译之后,会在同步代码块的前后分别形成monitorenter和monitorexit两个字节码指令,这两个字节码指令都需要一个reference类型的参数指明要锁定和解锁的对象。如果java程序指明对象的参数,那就是那个对象的ref;如果没有明确指定,根据syschronized修饰的是实例方法还是类方法,去取对应的对象实例或者Class对象来作为锁对象。
  根据虚拟机的规范要求,在执行monitorenter指令,首先要尝试获取对象的锁,如果对象没有被锁定(对象在内存那种存储的布局为3部分,对象头、实例数据、对其填充,其中对象头中分为两部分一部分是存储自身运行时数据称为Mark Word,哈希码,gc分代年龄,锁得标志位;另一部分为类型指针,用来确定他是那个类的实例)或者当前线程已经拥有对象锁,把锁的计数器加1,相应执行monitorexit就是将锁的计数器减1,当计数器为0,锁就被释放。如果获取失败,那当前线程就要阻塞等待,直到对象锁被另外的线程释放。

二、1.syschronized几种上锁方式的区别

syschronized可以修饰 (简单来说 只有对对象锁和类锁)
1. 普通方法
2. 静态方法
3. 修饰代码块(分为两种:锁对象和锁Class字节码文件)

修饰普通方法 就是对当前对象this(谁调用谁就是当前的对象)进行上锁
修饰static方法 就是对当前的Class类(方法在那个类里面就是哪个类)进行上锁
对象锁是基于对堆内存 对象的头部加锁信息
类锁是基于类对应的java.lang.Class对象加锁信息。
多个线程对同一个类的实例对象上锁和对这个类的class上锁是互不影响的

[JVM在装载完毕一个类的时候,还会给该类生成一个 java.lang.Class 的对象,由 类数据区里面的该类的this_class字段指向这个Class对象。 从而,类锁的实现原理可以转化为对象锁的原理 — 在对应的Class对象上加对象锁即可。]

使用区别:
  使用对象锁,除了获取当前对象的对象锁的线程,其他线程对当前对象所有需要使用对象锁的语句访问受到阻塞,但对不使用对象锁的语句访问不受影响
  使用类锁,除了获取该类的类锁的线程外,其他线程对该类所有需要使用类锁的方法的访问收到阻塞,没有使用类锁的语句访问没有影响。
类锁和对象锁的作用域不同,两者互不影响

三、synchronized解释

synchronized可以保证可见性、原子性。
内存可见性:
一个线程在释放syschronized锁之前,会将线程内存中的共享变量写回到主内存
一个线程在获取syschronized锁之后,会清空线程内部涉及到的共享变量,再从主内存读取
synchronized是可重入锁,为什么要有可重入锁,可重入锁的作用:
syschronized对同一个线程是可重入的,可重入的好处就是不会出现自己把自己锁死的情况,所以可重入锁的意义在于防止死锁

四、syschronized和lock的区别

synchronized的锁可重入、不可中断、非公平,而Lock锁可重入、可中断、可公平、绑定多个Condition.(两者皆可重入)

  1. synchronized是一个关键字 lock是一个接口是类
  2. synchronized无法获得所得状态,属于自动锁,发生异常会自动释放锁
  3. lock可以获得锁的状态,手动锁,发生异常不会自动释放要在finally里面自己手动释放
  4. synchronized是非公平锁 lock是公平锁
  5. synchronized不可中断 持有锁线程一直不释放,其他只能阻塞等待 lock可以设置时间进行放弃等待

你可能感兴趣的:(Java多线程)