并发:线程安全性

本文参考《java并发编程实战》,java并发必读书籍

关键词

  • 线程与锁
  • 共享的(Shared)状态:多个线程同时访问
  • 可变的(Mutable)状态:变量的值在其生命周期内可以发生变化
  • 同步机制:Synchronized, volatile类型变量, 显示锁(Explicit Lock),原子变量
  • 解决可变的状态变量并发错误的3个方案1.不共享,2.改为不可变,3.使用同步
  • 线程安全类与线程安全程序

 

一、什么是线程安全性

1.线程安全性定义

当多个线程访问某个类时,不管运行时环境采用何种调度方式,或者线程将如何交替执行,主调代码中不需要任何额外的同步和协同,这个类就能表现出正确的行为,那么就称这个类时线程安全的。

2.备注说明

  • a.最核心的概念就是  正确性
  • b.在线程安全类中封装了必要的同步策略,客户端(主调代码)无需进一步采取同步策略

 

二、原子性

1.竞态条件

最为常见的竞态条件是:先检查后执行(Check-Then-Act)

例如单例中的,这个单例是有问题的,可以参考特别完整及简单的单例模式

pulic class Singleton {
    private Singleton instance;
    
    private Singleton() {
    }

    public static Singleton() {
        if(instance == null) {//先检查,后执行
            instance = new Singleton();
        }
        return instance
    }
}

 

2、复合操作与原子操作

复合操作:是一组需要以原子方式执行的操作

原子操作:对于访问同一个状态的所有操作来说,这个操作是一个以原子方式执行的操作

 

三、加锁机制

1.内置锁

java提供的内置锁为同步代码块(Synchronize Block)

包含俩部分:一个作为锁的对象引用;一个作为由这个锁保护的代码块。

静态的synchronized方法以Class对象作为锁

内置锁也称为互斥体、互斥锁

 

2.重入

重入意味着获取锁的操作的粒度是线程,而不是调用

重入的实现方式:为每个锁关联一个获取计数值和一个所有者线程

重入进一步提升了加锁行为的封装性,因而简化了面向对象并发代码的开发

重入例子

public class Widget {
    public synchronized void doSomething() {
        ...
    }
}

public class LoggingWidget extends Widget {
    public synchronized void something() {
        ...
        super.doSomething();
    }
}

 

四、用锁来保护状态

共享状态的变量以独占的方式来访问,也就是以 串行形式来访问。

对于可能被多个线程同时访问的可变状态变量,在访问它的时候都需要持有同一个锁,在这种情况下,我们称状态变量是由这个锁保护的

对于每个包含的多个变量的不变性条件,其中涉及的所有变量都需要由同一个锁来保护

五、活跃性与性能

在简单性与性能之间存在互相制约因素。

当实现某个点同步策略时,一定不要盲目地为了性能而牺牲简单性(这可能破坏安全性)

当执行时间较长的计算或者可能无法快速完成的操作时(例如,网络I/O或者控制台I/O),一定不要持有锁

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值