Synchronized & volatile

synchronized 关键字介绍

synchronized 块是Java 提供的一种原子性内置锁, Java 中的每个对象都可以把它当作一个同步锁来使用, 这些Java 内置的使用者看不到的锁被称为内部锁,也叫作监视器(monitor)锁。线程的执行代码在进入synchronized 代码块前会自动获取内部锁,这时候其他线程访问该同步代码块时会被阻塞挂起。拿到内部锁的线程会在正常退出同步代码块或者抛出异常后或者在同步块内调用了该内置锁资源的wait 系列方法时释放该内置锁。内置锁是排它锁,也就是当一个线程获取这个锁后, 其他线程必须等待该线程释放锁后才能获取该锁。

由于Java 中的线程是与操作系统的原生线程一一对应的,所以当阻塞一个线程时,需要从用户态切换到内核态执行阻塞操作,这是很耗时的操作,而synchronized的使用就会导致上下文切换

当一个对象多个方法使用到synchronized时,调用synchronized锁住的每个方法都会锁住该对象。

https://www.cnblogs.com/paddix/p/5367116.html

synchronized 的内存语义

synchronized 的一个内存语义,这个内存语义就可以解决共享变量内存可见性问题。进入synchronized 块的内存语义是把在synchronized 块内使用到的变量从线程的工作内存中清除,这样在synchronized 块内使用到该变量时就不会从线程的工作内存中获取,而是直接从主内存中获取。退出synchroni zed 块的内存语义是把在synchroni zed 块内对共享变量的修改刷新到主内存。

其实这也是加锁和释放锁的语义,当获取锁后会清空锁块内本地内存中将会被用到的共享变量,在使用这些共享变量时从主内存进行加载,在释放锁时将本地内存中修改的共享变量刷新到主内存。

除可以解决共享变量内存可见性问题外, synch ronized 经常被用来实现原子性操作。另外请注意, synchronized 关键字会引起线程上下文切换并带来线程调度开销。

volatile

该关键字可以确保对一个变量的更新对其他线程马上可见。当一个变量被声明为volatile 时,线程在写入变量时不会把值缓存在寄存器或者其他地方,而是会把值刷新回主内存。当其他线程读取该共享变量时 ,会从主内存重新获取最新值,而不是使用当前线程的工作内存中的值。

volatile 的内存语义和synchronized 有相似之处,具体来说就是,当线程写入了volatile 变量值时就等价于线程退出synchronized同步块(把写入工作内存的变量值同步到主内存),读取volatile 变量值时就相当于进入同步块( 先清空本地内存变量值,再从主内存获取最新值) 。

写volatile 变量时,可以确保volatile 写之前的操作不会被编译器重排序到volatile 写之后。读volatile 变量时,可以确保volatile 读之后的操作不会被编译器重排序到volatile读之前。

使用场景:

  • 写入变量值不依赖、变量的当前值时。因为如果依赖当前值,将是获取一计算一写入三步操作,这三步操作不是原子性的,而volatile 不保证原子性
  • 读写变量值时没有加锁。因为加锁本身已经保证了内存可见性,这时候不需要把变量声明为volatile 的。

参考:

  1. 《Java并发编程之美》
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值