synchronized的底层实现原理

简述:
什么是synchronized?sysnchronized就是同步的意思,故名思意是用来保证线程安全的。

synchronized(同步):当一个或者多个线程同时访问一个临界资源的时候,只允许有一个

线程访问,其他线程排队等候。当这个线程彻底把锁释放之后,才允许下个线程去访问

该临界资源,并且再次获取该锁,执行下面操作,直至把锁释放。下图可以清楚的展示该结

论。

在这里插入图片描述
在这里插入图片描述

图一:没有加synchronized关键字,当多个线程并发访问该资源的时候,当其中一

个线程去执行count--操作,将值减一,如果第一个线程读到它是0,然会减1,当这

个线程还没有将数据保存到自己的线程栈中,第二个线程又来将他的值又改为0,所以

结果为0。这就说明在访问临界资源的时候,他的值可能被其它线程修改。

图二:
 加了同步关键字,synchronized,也就是说多个线程并发访问该临界资源的时候,当

其中一个线程去执行count--操作的时候,读到它是0,然后进行减1,然后进行打印

当第二个线程来访问该资源的时候,首先看第一个线程是否释放该锁,释放该锁,第

二个线程获取该锁,执行操作,也就是说只允许一个线程对它操作,其它线程不允

许修改该操作。

2.介绍完概念型的东西,再来说说它的原理,它是怎么执行的,作用在哪
里?它是给对象头(markword和class pointer)上锁,锁的是对象头。
那么对象在内存中是如何布局的呢?
在这里插入图片描述
上图就清晰的展示对象在内存的的关系布局图,那么具体的这几部分都代表什么呢?一一来说下:

1. markword:存储一些存储锁的信息,有偏向锁记录,偏向时间戳,锁标志位,偏向线

   程,id,GC分代年龄,hahcode,basied_lock(锁状态)。指针记录。

2.类型指针(class pointer):类元数据指针,当我们new出来一个对象,可以根据
  
  该指针到jvm虚拟机的方法区找到对应的类。就知道对象是哪个类的实例。

3.实例数据(instance):位于虚拟机的堆区,存放实例数据。

4.对齐填充(padding):什么也不存放,由于虚拟机给默认的对象是8的倍数,当不够
   
   8的倍数,会自动填充。

介绍完对象的信息,我们并且知道synchronized上锁的地方是对象头的markword,那么jdk8中的markword的实现是怎样的呢?
在这里插入图片描述
总共记录的了4种锁状态,其中GC是垃圾回收器,当啥时候堆内存满了的时候才启用它,一般虚拟机默认不会启用。

无锁态: 在堆内存中开辟25bit的空间来存放对象的hashcode,开辟4bit的空间存

GC分代年龄。1bit空间用来判断是否偏向锁:0,2bit存放锁标志位:01。

轻量级锁:直接开辟30bit的空间来存放指向自身线程栈记录的指针,开辟2bit存放

锁标志位:00

重量级锁:开启30bit的空间来存放互斥量(重量级锁)的指针。开辟2bit存放锁标志

位:10

GC分代年龄:存放的数据为空,开辟2bit空间存放锁标识位:11

偏向锁:开辟23bit空间用来标识自身线程栈的线程ID,2bit存放偏向时间戳(epoch),

4bit存放GC分代年龄,1bit用来标识是否为偏向锁位:1,2bit来标识锁标志位。

这就是jdk8对markword的实现。那么到底是怎么上锁的呢?锁的是对象哪里呢?
在这里插入图片描述
上面就是通过jol框架打印出来的对象关系布局图,红色标记为就记录我们的锁状态和锁标志位。这就是锁的对象头。0位无锁状态。
那么synchronized是可以从以下3方面的实现:

1.源码角度: 在这里插入图片描述
这就是源码角度的对象上锁。

2.字节码层级的实现:通过monitorenter和monitorexit指令来给对象上锁和解锁,当执行monitorenter的时候给对象加锁,获取monitor对象监视器,进行以下执行操作。当执行完monitorexit释放锁。大家看下图:
在这里插入图片描述
上图我们看出从字节码层级上的synchronized的实现。

3.HotSpot的实现(可以查看openjdk的源码,直接从github官网下载):

直接奉上源码的实现:在这里插入图片描述 在这里插入图片描述

首先,说明下,在软件层面的最终实现是:lock指令 lock  cmpxchg  =cas+修改变量值

在硬件层面,lock指令在执行后面指令的时候锁定了一个北桥信号(电信号)。

在c++源码中:有一条汇编指令:asm  volatile (LOCK_IF MP(%4) "cmpxchg  %1,(%3)")

这行代码是已经接入操作系统了,volatile的底层最终实现也是该lock指令

至此,我们就把synchronized的实现原理以及在哪里上锁弄明白了,这是自己对此的了解,望对大家有帮助。后面我会给大家分享锁竞争与锁升级的过程。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: synchronized关键字的底层实现原理涉及到Java对象头的概念。在Java对象头中,有一个表示锁状态的标志位,它用来标识对象的锁状态。当线程进入一个synchronized方法或代码块时,会尝试获取对象的锁。如果该锁没有被其他线程占用,则该线程会成功获取锁并进入临界区。如果该锁已经被其他线程占用,则该线程会进入阻塞状态,直到锁被释放。当线程执行完synchronized方法或代码块后,会释放锁。 在JVM中,synchronized关键字实现的锁有两种,分别为偏向锁和重量级锁。偏向锁是一种优化机制,它在对象创建时会将锁标志位初始化为偏向模式。当一个线程获取该对象的锁时,会将当前线程的ID记录在对象头中,并将锁标志位设置为偏向模式。以后该线程再次获取该对象的锁时,无需竞争,可以直接获取。重量级锁则是一种比较传统的锁机制,它使用操作系统的互斥量来实现锁。当多个线程竞争同一对象的锁时,会进入阻塞队列,等待锁被释放。 因此,synchronized关键字的底层实现原理就是通过Java对象头中的标志位来实现锁状态的记录和判断,并通过偏向锁和重量级锁来优化锁的竞争。 ### 回答2: synchronizedJava中用来实现线程同步的关键字,它保证了在同一时间只有一个线程可以进入被synchronized修饰的代码块或方法。synchronized底层实现原理涉及到Java对象头、Monitor、线程间通信等。 每个Java对象在内存中都会有一个对象头,对象头中包含了一些元数据字段,其中有一个字段用来记录当前对象的锁信息。当一个线程进入synchronized代码块时,首先会尝试对对象加锁,如果对象的锁信息表明已经被其他线程锁定,则该线程会进入阻塞状态,等待其他线程释放锁。如果对象的锁信息表明还没有被其他线程锁定,则将对象头中的锁信息设置为该线程,并且将一个Monitor关联到该对象上。 Monitor是Java中用来实现监视器锁的机制,它与每个Java对象关联。Monitor内部维护了一个线程等待队列和一个拥有锁的线程。每个Monitor对象只能拥有一个线程,其他线程需要获取锁时只能进入等待队列。当某个线程执行完synchronized代码块或方法时,会释放锁,并且唤醒等待队列中的一个线程来竞争锁。 线程间的通信是通过底层的wait()、notify()和notifyAll()方法实现的。当一个线程执行wait()方法时,它会释放锁并进入阻塞状态,等待其他线程调用notify()或notifyAll()方法来唤醒它。唤醒的线程将进入就绪状态,并与其他线程竞争锁,竞争成功后将继续执行。 总结起来,synchronized底层实现原理是通过Java对象头、Monitor和线程间的通信来实现的。它保证了在同一时间只有一个线程可以进入被synchronized修饰的代码块或方法,避免了多个线程对共享资源的并发访问造成的数据不一致问题。 ### 回答3: synchronizedJava中用于实现线程同步的关键字,可以用于修饰方法或代码块,保证多个线程对同一资源进行访问时的互斥。 synchronized底层实现原理是基于对象的监视器(Monitor)机制。在Java中的每一个对象都会有一个与之关联的Monitor对象,Monitor对象用于同步对共享资源的访问。当一个线程遇到synchronized修饰的代码块或方法时,它首先需要获得对象的Monitor对象的锁。若锁已经被其他线程持有,则该线程会进入阻塞状态,直到锁被释放。当该线程获得锁之后,它就可以执行临界区内的代码了。 当一个线程执行完synchronized代码块或方法后,会释放对Monitor对象的锁,其他处于等待的线程就有机会获得锁,进入临界区执行代码。这样就保证了在任意时刻,只有一个线程可以获得锁,其他线程需要等待,实现了对共享资源的互斥访问。 synchronized通过内置的锁机制来实现线程间的同步,确保了数据的一致性和完整性。它基于底层的Monitor机制利用了操作系统的原子性操作,保证了多线程并发执行时的正确性。但是,在synchronized的机制下,一个线程获得了对象的锁之后,其他线程必须等待,可能会造成线程的阻塞和延迟。此外,在一些特殊情况下,可能会出现死锁的问题,即多个线程相互等待对方释放锁。 总之,synchronized是一种可靠的线程同步机制,通过Monitor对象的锁机制实现对共享资源的互斥访问。它的底层实现原理是基于对象的监视器(Monitor)机制,利用锁和等待队列来控制线程的执行和互斥访问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值