美文网首页
二、线程安全性

二、线程安全性

作者: RainySpring | 来源:发表于2020-04-17 00:30 被阅读0次

要编写线程安全的代码其核心在于要对状态访问操作进行管理,特别是对共享的(shared)和可变的(Mutable)状态的访问。
-- 《Java并发编程实战》

知识储备:非状态、竞争条件、原子操作

1、多线程访问同一个可变的状态变量,怎么解决?

  • 不在线程之前共享该状态变量
  • 将这个可变的状态变量改为不变的
  • 在访问状态变量使用同步

2、什么是线程安全性?
当多个线程访问某个类时,这个类始终表现出正确的行为。这个类就是线程安全的。

3、什么是无状态?
无状态对象一定是线程安全的,就是没有包含任何域,也不包括任何对其他类中域的引用。大多数Servlet都是无状态的。


image.png

非原子性操作会造成 竞态条件:读取-修改-写入
还有一种 延迟初始化(单例模式)的竞态条件:先检查后执行
这些计算的正确性取决于多个线程的交替执行时序,就会发生竞态条件。

private SingleObject  single = null;
public getInstance(){
  if  (single == null){
      single = new SingleObject();
  }
}

4、竞态条件在并发情况永远是错误的吗?
并不是总是产生错误,还是需要某种不恰当的执行时序。

5、复合操作和原子操作
假设有2个操作A和B,对于执行A的线程来说,另一个执行B的线程要么全部执行完,要么完全不执行,那么A和B对彼此来说就是原子操作,反之是复合操作。
eg. int i = 0;i++ 就是一种读取-修改-写入的复合操作
eg.AtomicLong i = new AtomicLong (0); i.incrementAndGet();就是原子操作
AtomicLong 是线程安全的对象,在实际情况中我们尽量使用这种线程安全的对象来管理类的状态。

加锁机制

1、原子操作无法解决的问题

如果一个类中有更多的状态变量时,是否只需要加入线程安全状态变量就足够了?
不是,依然存在竞态条件

//2个原子状态量
public AtomicInteger a = new AtomicInteger(0);
public AtomicInteger b = new AtomicInteger(0);
    public void service(){
        if(...){
            a.get(); //1
        }else{
            a.incrementAndGet();//2
            b.incrementAndGet();
        }
    }

虽然状态变量都是原子操作,假设线程小红刚跑到1位置,正要获取a的值,此时线程小明跑到2位置并将a的值累加了,那么小红获取的值就是个不正确状态的值!

2、内置锁(互斥锁) - 同步代码块(Synchronized)

synchronized(lock){
  //访问或修改 由锁保护的共享状态
}

lock:以class为锁;代码块组成一组不可分割的原子单元。

3、锁重入

某个线程请求一个由其他线程持有的锁时,当前线程会被阻塞;
但是试图获取一个由自己持有的锁,这个请求就会成功,否则造成死锁。
“重入”意味着锁的操作粒度是“线程”,而不是“调用”。

4、一种加锁的约定

将所有的可变状态都封装在对象内部,通过对象的内置锁对其进行同步,就不会出现并发访问了。

5、活跃性和性能

synchronized会造成一种串行阻塞性的不良并发,性能低;
怎么缓解?
掌握在简单性(最简单的就是对整个方法进行同步)与并发性(对尽可能短的代码块进行同步)之间的平衡,既不能太简单省事,也不能加太多的同步代码块,分的太短太细。

//这种同步代码短,但是在for循环中锁次数较多 影响性能
for(){
  synchronized(this){
  }
}
//这样加比较好,所以要在这两者间平衡
synchronized(this){
  for(){}
}

学习中,有不足之处欢迎指出!感谢

相关文章

  • 线程安全性(二)

    原子性 - 锁 原子性提供了互斥访问,同一时刻只能有一个线程对它进行操作。能保证同一时刻只有一个线程进行操作的,除...

  • 线程安全性(二)

    原子性提供互斥访问,同一时刻只能有一个线程来对它进行操作 synchronized:依赖于JVM,属于不可中断锁,...

  • 二、线程安全性

    要编写线程安全的代码其核心在于要对状态访问操作进行管理,特别是对共享的(shared)和可变的(Mutable)状...

  • EffectiveJava第十章第五节

    线程安全性的文档化 并非出现synchronized关键字就是线程安全性文档化了。实际上,一个类支持的线程安全性有...

  • String的线程安全

    线程安全性 说道有关string的线程安全性,大家想到的肯定时stringbuffer和stringbuilder...

  • Java并发编程 线程安全性

    什么是线程安全性 线程安全性:当多个线程访问某个类时,不管运行时采用何种调度方式或者这些线程将被如何交替执行,并且...

  • java并发编程实战2~3

    2 线程安全性 2.1 什么是线程安全性 当多个线程访问某个类时,不管运行时环境采用何种调度方式或者这些线程将如何...

  • 谈谈并发编程中的线程安全性

    1. 线程安全性 在单线程程序中,我们并不需要去考虑线程的安全性。但是在多线程程序中,由于多个线程要共享相同的内存...

  • 线程安全性(一)

    参考线程安全性总结 CountDownLatchCountDownLatch 可以阻塞线程并保证线程在满足某种特定...

  • 高并发编程03 ~ 线程安全性

    这节我们讨论一个话题:线程安全性 一、概念 线程安全性:当多个线程同时访问某个资源的时候,不管环境采用何种调度方式...

网友评论

      本文标题:二、线程安全性

      本文链接:https://www.haomeiwen.com/subject/ehufvhtx.html