线程安全与数据同步

共享资源

共享资源指的是多个线程同时对同一份资源进行访问(读写操作),被多个线程访问的资源就称为共享资源,如何保证多个线程访问到的数据是一致的,则被称为数据同步或者资源同步。


synchronized关键字

synchronized关键字可以实现一个简单的策略来防止线程干扰和内存一致性错误,如果一个对象对多个线程是可见的,那么对该对象的所有读或者写都将通过同步的方式来进行。

  • synchronized关键字提供了一种锁的机制,能够确保共享变量的互斥访问,从而防止数据不一致问题的出现
  • synchronized关键字包括 monitor enter 和 monitor exit 两个JVM指令,它能够保证在任何时候任何线程执行到monitor enter 成功之前都必须从主内存中获取数据,而不是从缓存中,在monitor exit运行成功之后,共享变量被更新后的值必须刷入主内存
  • synchronized的指令严格遵守 java happens-before 规则,一个 monitor exit 指令之前必定要有一个monitor enter

synchronized可以用于对代码块和方法进行修饰,而不能够用于对class以及变量进行修饰。

  • 同步方法
  • 同步代码块

Monitorenter
每个对象都与一个monitor相关联,一个monitor的lock的锁只能被一个线程在同一时间获得,在一个线程尝试获得与对象关联monitor的所有权时会发生如下几件事情:

  • 如果monitor的计数器为0,则意味着该monitor的lock还没有被获得,某个线程获得之后将立即对该计数器加1,从此该线程就是这个monitor的所有者了
  • 如果一个已经拥有该monitor所有权的线程重入,则会导致monitor计数器再次累加
  • 如果monitor已经被其他线程所拥有,则其他线程尝试获取该monitor的所有权时,会被陷入阻塞状态直到monitor计数器变为0,才能再次尝试获取对monitor的所有权

Monitorenter
释放对monitor的所有权,想要释放对某个对象关联的monitor的所有权的前提是,你曾经获得了所有权。释放monitor所有权的过程比较简单,就是将monitor的计数器减1,如果计数器的结果为0,那就意味着该线程不再拥有对该monitor的所有权,通俗地讲就是解锁。与此同时被该monitor block 的线程将再次尝试获得对该monitor的所有权。

使用synchronized需要注意的问题

  • 与monitor关联的对象不能为空
  • synchronized的作用域太大,效率会降低,甚至丧失并发的优势
  • 不同的monitor企图锁相同的方法
  • 多个锁的交叉导致死锁

This Monitor 和 Class Monitor
this monitor: 被synchronized修饰的同一个实例对象的两个不同方法,monitor其实是这个实例的引用
class monitor:被synchronized修饰的同一个对象的两个不同类方法(静态方法),monitor其实是这个类实例的引用


synchronized关键字的缺陷

synchronized关键字提供了一种排他式的数据同步机制,某个线程在获取monitor lock的时候会被阻塞,而这种阻塞有两个明显的缺陷:
第一:无法控制阻塞时长
第二:阻塞不可被中断


程序死锁的原因以及如何诊断

程序死锁

  • 交叉锁可导致程序出现死锁
  • 内存不足
  • 一问一答式的数据交换
  • 数据库锁
  • 文件锁
  • 死循环引起的死锁

死锁诊断

  • 交叉锁引起的死锁:jstack工具
  • 死循环引起的死锁:jprofile工具
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值