synchronized总结

目录

一、synchronized的特性

1.1 原子性

1.2 可见性

1.3 有序性

1.4 可重入性

二、synchronized的使用

2.1 修饰普通方法

2.2 修饰静态方法

2.3 修饰代码块

三、synchronized的锁机制

 3.1 偏向锁

3.2 轻量级锁

3.3 重量级锁

一、synchronized的特性

1.1 原子性

原子性是指一个操作或者多个操作,要么全部执行并且在执行的过程中不会被任何因素打断,要么就都不执行.

一条Java语句不一定是原子的,也不一定是一条指令,Java中对基本数据类型的变量读取和赋值操作都是原子性操作,也就是说这些操作是不可中断的,要么执行,要么不执行,像++,+=等操作符就不是原子的,他们是分成读取 计算 赋值几步操作的,有可能这些步骤还未完成就被赋值了,这就是脏读问题,无法保证原子性.

synchronized修饰的类或对象的所有操作都是原子的,因为在执行操作之前必须先获得类或对象的锁,直到执行完才能释放。

1.2 可见性

可见性是指多个线程访问一个资源时,该资源的状态、值信息等对于其他线程都是可见的。 synchronized和volatile都具有可见性,其中synchronized对一个类或对象加锁时,一个线程如果要访问该类或对象必须先获得它的锁,而这个锁的状态对于其他任何线程都是可见的,并且在释放锁之前会将对变量的修改刷新到共享内存当中,保证资源变量的可见性

1.3 有序性

 有序性程序执行的顺序按照代码先后执行 ,synchronized和volatile都具有有序性,Java允许编译器和处理器对指令进行重排,但是指令重排并不会影响单线程的顺序,它影响的是多线程并发执行的顺序性。synchronized保证了每个时刻都只有一个线程访问同步代码块,也就确定了线程执行同步代码块是分先后顺序的,保证了有序性。

1.4 可重入性

synchronized和ReentrantLock都是可重入锁。当一个线程试图操作一个由其他线程持有的对象锁的临界资源时,将会处于阻塞状态,但当一个线程再次请求自己持有对象锁的临界资源时,这种情况属于重入锁。通俗一点讲就是说一个线程拥有了锁仍然还可以重复申请锁。

  1. 既是悲观锁,也是乐观锁,开始时是乐观锁, 如果锁冲突频繁, 就转换为悲观锁.
  2. 既是轻量级锁,也是重量级锁(自适应),开始是轻量级锁实现, 如果锁被持有的时间较长, 就转换成重量级锁.
  3. 轻量级锁部分基于自旋锁实现,重量级锁部分基于挂起等待锁来实现
  4. 不是读写锁
  5. 是非公平锁
  6. 是可重入锁 

二、synchronized的使用

2.1 修饰普通方法

多线程环境下,每次只能有一个线程访问该方法。

public synchronized void func() {
    //代码
}

2.2 修饰静态方法

就是给当前类加锁,会作用于类的所有对象实例 ,进入同步代码前要获得 当前 class 的锁。因为静态成员不属于任何一个实例对象,是类成员( static 表明这是该类的一个静态资源,不管 new 了多少个对象,只有一份)。所以,如果一个线程 A 调用一个实例对象的非静态 synchronized 方法,而线程 B 需要调用这个实例对象所属类的静态 synchronized 方法,是允许的,不会发生互斥现象,因为访问静态 synchronized 方法占用的锁是当前类的锁,而访问非静态 synchronized 方法占用的锁是当前实例对象锁

synchronized void staic Func() {
  //代码
}

2.3 修饰代码块

   this 代表当前实例对象,锁住的是当前实例:

synchronized(this) {
    for (int i = 0; i < 10; i++) {
		//代码
    }
}

.class锁住的是当前类的 class 对象锁:

synchronized(Main.class) {
    for (int i = 0; i < 10; i++) {
        //代码
    }
}

synchronized 关键字加到 static 静态方法和 synchronized(class) 代码块上都是是给 Class 类上锁。

synchronized 关键字加到实例方法上是给对象实例上锁。

三、synchronized的锁机制

从JDK5引入了现代操作系统新增加的CAS原子操作( JDK5中并没有对synchronized关键字做优化,而是体现在J.U.C中,所以在该版本concurrent包有更好的性能 ),从JDK6开始,就对synchronized的实现机制进行了较大调整,包括使用JDK5引进的CAS自旋之外,还增加了自适应的CAS自旋、锁消除、锁粗化、偏向锁、轻量级锁这些优化策略。由于此关键字的优化使得性能极大提高,同时语义清晰、操作简单、无需手动关闭,所以推荐在允许的情况下尽量使用此关键字,同时在性能上此关键字还有优化的空间。

锁主要存在四种状态,依次是:无锁状态、偏向锁状态、轻量级锁状态、重量级锁状态,锁可以从偏向锁升级到轻量级锁,再升级的重量级锁。但是锁的升级是单向的,也就是说只能从低到高升级,不会出现锁的降级。

 3.1 偏向锁

第一个尝试加锁的线程, 优先进入偏向锁状态.偏向锁不是真的 “加锁”, 只是给对象头中做一个 “偏向锁的标记”, 记录这个锁属于哪个线程.如果后续没有其他线程来竞争该锁, 那么就不用进行其他同步操作了(避免了加锁解锁的开销)

如果后续有其他线程来竞争该锁(刚才已经在锁对象中记录了当前锁属于哪个线程了, 很容易识别 当前申请锁的线程是不是之前记录的线程), 那就取消原来的偏向锁状态, 进入一般的轻量级锁状态.偏向锁本质上相当于 “延迟加锁” . 能不加锁就不加锁, 尽量来避免不必要的加锁开销.

3.2 轻量级锁

随着其他线程进入竞争, 偏向锁状态被消除, 进入轻量级锁状态(自适应的自旋锁).此处的轻量级锁就是通过 CAS 来实现.

通过 CAS 检查并更新一块内存 (比如 null => 该线程引用)如果更新成功, 则认为加锁成功如果更新失败, 则认为锁被占用, 继续自旋式的等待(并不放弃 CPU).自旋操作是一直让 CPU 空转, 比较浪费 CPU 资源.因此此处的自旋不会一直持续进行, 而是达到一定的时间/重试次数, 就不再自旋了.也就是所谓的 “自适应”

3.3 重量级锁

如果竞争进一步激烈, 自旋不能快速获取到锁状态, 就会膨胀为重量级锁  执行加锁操作, 先进入内核态在内核态判定当前锁是否已经被占用 如果该锁没有占用, 则加锁成功, 并切换回用户态.如果该锁被占用, 则加锁失败. 此时线程进入锁的等待队列, 挂起. 等待被操作系统唤醒.经历了一系列的沧海桑田, 这个锁被其他线程释放了, 操作系统也想起了这个挂起的线程, 于是唤醒 这个线程, 尝试重新获取锁

  • 11
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
synchronized是一种关键字,可以实现线程之间的同步和互斥。在Java中,synchronized是可重入的,也就是说同一个线程可以多次获取同一把锁,或者在调用自己类中的其他synchronized方法/块时不会阻碍线程的执行。这意味着同一个线程可以连续地获取同一个对象的锁,而不会造成死锁或阻塞。这种可重入性是由Java虚拟机自动管理的,通过监视器锁(monitor)来实现。当线程第一次获取锁时,会在锁的持有计数器上加1,之后每次成功获取锁,计数器就会增加。只有当计数器归零时,锁才会被完全释放。因此,同一个线程在获取锁后,可以再次获取同一把锁而不会被阻塞。这种特性使得在synchronized方法/块中调用其他synchronized方法/块成为可能,而不会出现死锁或死循环的情况。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [synchronized总结](https://blog.csdn.net/weixin_39559282/article/details/114273936)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *3* [synchronized——可重入性](https://blog.csdn.net/SmuEdward/article/details/54629771)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值