【JavaEE】多线程之锁(synchronized)与volatile关键字

目录

1.synchronized的特性

1.1互斥性 

1.2可重入性

 2.synchronized 使用示例

2.1直接修饰普通方法: 锁的 SynchronizedDemo 对象

2.2修饰静态方法: 锁的 SynchronizedDemo 类的对象

2.3修饰代码块: 明确指定锁哪个对象

3.volatile关键字

3.1volatile 能保证内存可见性

4.synchronized和volatile的区别 


1.synchronized的特性

1.1互斥性 

synchronized 会起到互斥效果, 某个线程执行到某个对象的 synchronized 中时, 其他线程如果也执行到同一个对象 synchronized 就会阻塞等待,当一个线程在执行加锁的代码块时,另一个线程再来加锁就无法加上,这就是互斥性。

  • 进入 synchronized 修饰的代码块, 相当于 加锁
  • 退出 synchronized 修饰的代码块, 相当于 解锁

 举例说明一下互斥性,相当于我们上厕所,一个坑位只能有人使用。当有人进入的时候,另一个人就无法进入,

 

加锁:就相当于厕所里面有人,并且锁着门了。

解锁: 就相当于厕所里面人出来了,它开始叫队伍中的一个人。叫人就算是唤醒等待队列中的一个线程。

阻塞等待定义:针对每一把锁, 操作系统内部都维护了一个等待队列. 当这个锁被某个线程占有的时候, 其他线程尝试进行加锁, 就加不上了, 就会阻塞等待, 一直等到之前的线程解锁之后, 由操作系统唤醒一个新的线程, 再来获取到这个锁。
注意:

  • 上一个线程解锁之后, 下一个线程并不是立即就能获取到锁. 而是要靠操作系统来 "唤醒". 这
    也就是操作系统线程调度的一部分工作.
  • 假设有 A B C 三个线程, 线程 A 先获取到锁, 然后 B 尝试获取锁, 然后 C 再尝试获取锁, 此时 B
    和 C 都在阻塞队列中排队等待. 但是当 A 释放锁之后, 虽然 B 比 C 先来的, 但是 B 不一定就能
    获取到锁, 而是和 C 重新竞争, 并不遵守先来后到的规则.

1.2可重入性

 synchronized 同步块对同一条线程来说是可重入的,不会出现自己把自己锁死的问题。

要想了解可重入性,必须先了解“死锁”,死锁就是按照之前对于锁的设定, 第二次加锁的时候, 就会阻塞等待. 直到第一次的锁被释放, 才能获取到第二个锁. 但是释放第一个锁也是由该线程来完成, 结果这个线程已经躺平了, 啥都不想干了, 也就无法进行解锁操作. 这时候就会死锁。

Java 中的 synchronized 是 可重入锁, 因此没有上面的问题

 2.synchronized 使用示例

synchronized 本质上要修改指定对象的 "对象头". 从使用角度来看, synchronized 也势必要搭配一个具体的对象来使用

2.1直接修饰普通方法: 锁的 SynchronizedDemo 对象

public class SynchronizedDemo {
    public synchronized void methond() {
        }
}

2.2修饰静态方法: 锁的 SynchronizedDemo 类的对象

public class SynchronizedDemo {
    public synchronized static void method() {
    }
}

2.3修饰代码块: 明确指定锁哪个对象

public class SynchronizedDemo {
    public void method() {
        synchronized (this) {
        }
    }
}

 我们重点要理解,synchronized 锁的是什么. 两个线程竞争同一把锁, 才会产生阻塞等待,两个线程分别尝试获取两把不同的锁, 不会产生竞争.

3.volatile关键字

3.1volatile 能保证内存可见性

代码在写入 volatile 修饰的变量的时候

  • 改变线程工作内存中volatile变量副本的值
  • 将改变后的副本的值从工作内存刷新到主内存 

代码在读取 volatile 修饰的变量的时候

  • 从主内存中读取volatile变量的最新值到线程的工作内存中 
  • 从工作内存中读取volatile变量的副本

volatile的作用:前面我们讨论内存可见性时说了, 直接访问工作内存(实际是 CPU 的寄存器或者 CPU 的缓存), 速度非常快, 但是可能出现数据不一致的情况.加上 volatile , 强制读写内存. 速度是慢了, 但是数据变的更准确了

4.synchronized和volatile的区别 

volatile 和 synchronized 有着本质的区别. synchronized 能够保证原子性, volatile 保证的是内存可见性.

  • 14
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 10
    评论
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

爱吃大白菜  

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值