专业的JAVA编程教程与资源

网站首页 > java教程 正文

Java线程安全与锁深入探究(java的线程安全涉及到的关键字)

temp10 2025-03-19 02:28:51 java教程 9 ℃ 0 评论

为什么会有线程不安全

首先,线程不安全原理上是由于共享变量不可见的引起的

java内存模型

Java线程安全与锁深入探究(java的线程安全涉及到的关键字)

  • 变量都存于主内存中,当线程1使用变量时,会将变量从主内存取出,放入工作内存
  • 所有线程操作的都是自己工作内存中的变量
  • 线程操作变量时,首先判断工作内存命中与否,如是则操作工作内存,否则取主内存并同步到工作内存,然后操作工作内存

问题:该机制下如果多线程同时操作,则会存在工作内存与主内存不统一,导致所谓的共享变量不可见的问题

各种锁方案

1 Synchronized 解决共享变量同步问题

  • 线程进入synchronized块,java会清除工作内存中变量的内容,从主内存获取,同步到工作内存中
  • 操作完毕以后,释放锁时,会将工作内存中的内容同步到主内存中;

问题:多个线程争抢sync临界区资源,会导致线程上下文切换,增加线程调度的开销

2 Volatile 共享变量不可见的轻量级解决方案

  • 解决问题一:写入volatile变量 等同于 离开synchronized块,java会保证立即会刷新到主内存中
  • 解决问题二:读取volatile变量 等同于 进入synchronized块 ,清除工作内存中变量的内容,从主内存获取,同步到工作内存中

问题:不能解决依赖变量a本身: a=a+1(错误),获取=>修改=>写入 这3步本身不是原子性的,不能保证线程安

3 CAS 解决线程获取不到锁,阻塞等待的问题

compareAndSet(expect,update): 如果符合当前预期值,则可以更新成update值,否则返回。

线程执行cas方法以后,可以选择循环等待,或者跳过等待等方式,避免阻塞等待

4 AtomicLong:针对单个变量的原子性操作,多个线程间共享,保证线程安全

通过volatile变量+cas方式,实现单个变量的原子性操作

适合场景:单进程全局计数器,或者累加器

问题:多个线程操作AtomicLong,都是在争抢同一个原子变量,性能不高。

可以使用LongAdder解决

结语

以上介绍了各种锁原理和适用场景,抛砖引玉,大家可以在平时编码对应的使用。

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表