线程安全——定义及实现

线程安全级别

安全程度从强到弱:不可变 绝对线程安全 相对线程安全 线程兼容 线程对立

  1. 不可变 不可变的对象一定是线程安全的(前提this引用没有逃逸)
    1. 基本类型只要定义未final,就可以保证不可变
    2. 如果是引用类型,需要保证对象的状态不会受对象行为影响;所以引用类型的不安全在于可能线程一判断某对象状态后,另一线程进行了改变。
    3. 符合不可变要求的类型:String、Number的子类:Integer、Long、Short、、、(除BigInteger、BigDecimal等由数组存储的值和AtomicInteger、AtomicLong类型)
  2. 绝对线程安全: 任何情况下,调用者不需要任何同步措施,仍可以安全运行。很难实现,jdk提供的类也大多不是绝对线程安全。(不可变一定是绝对线程安全)
  3. 相对线程安全:通常意义上的线程安全——对某个对象的单独的操作是线程安全的。
  4. 线程兼容:大多数jdk的api都是这样——调用端正确使用同步可以保证线程安全
  5. 线程对立:不管采用什么同步措施,都会线程不安全;例如:
    1. Thread.suspend和Thread.resume 两线程同时对另一线程分别调用这两个方法必定产生死锁
    2. 原因:suspend停止不释放资源,当另一线程resume之前锁定已被锁定资源,必定产生死锁

线程安全实现方法

  1. 互斥同步/阻塞同步:互斥是方法,同步是目的;最大的问题:线程阻塞和唤醒带来的性能问题
    1. 互斥实现方法:
      1. 临界区(CriticalSection)
      2. 信号量(Semphore)
      3. 互斥量(Mutex)
    2. java中的实现方法:
      1. synchronized:
        1. 同步代码块编译之后,代码块前后会出现moniterenter和moniterexit的字节码指令,这两个命令需要引用类型的参数来指明需要锁定和解锁的对象
        2. (为什么不能锁基本类型嘞??)加锁是为了保证只有一个线程可以访问该变量,进而实现同步,但是基本类型可以直接final不需要多此一举。编译器报错——需要Object类型而不是int类型
        3. 如果synchronized修饰方法:实例方法锁定实例、类方法锁定类对象
        4. 执行moniterenter时首先尝试获取锁,如果当前无锁或者锁的拥有者是当前线程,锁的计数器加一,否则当前线程等待直到对象锁被释放
        5. synchronized重量锁:阻塞或唤醒线程需要从用户态到内核态
        6. synchronized 可重入
        7. 优化 : 自旋锁,循环判断是否锁被释放,假如锁被释放了,就不需要阻塞线程,不浪费cpu时间
      2. reentryLock:基本用法和synchronized相同,还增加了些高级功能:
        1. 等待可中断
        2. 公平非公平(synchronized的是否公平?非公平)
        3. 锁可以绑定多个条件 new Condition之后await阻塞,signalAll打断
  2. 非阻塞同步:乐观的并发策略,先进性操作,如果没有其他线程争用,则操作成功,如果操作失败,需要进行补救(比如不断重试);
    1. 这种实现需要硬件的支持:因为冲突检测和操作需要原子性,这类指令有:CAS(其余的P394)
  3. 无同步方案 假如一个方法本来就不涉及共享数据,那它就无须任何同步
    1. 可重入代码 共同特征:
      1. 不依赖存储在堆上的数据和公用的系统资源、用到的状态变量都由参数传入、不调用非可重入的方法等
      2. 判断方法:如果一个方法的返回结果可预测——只要输入了相同的树,就能返回相同的结果,那就满足可重入性,也就线程安全
    2. 线程本地存储:如果一个代码需要的数据必须与其他代码共享,假如这些共享数据的代码可以在同一线程内运行,那么就无须同步也可以保证线程之间不出现数据争用问题。java中的ThreadLocal
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值