2021-06-29

								软件构造线程安全
								
线程安全是多线程编程时的计算机程序代码中的一个概念。在拥有共享数据的多条线程并行执行的程序中,线程安全的代码会通过同步机制保证各个线程都可以正常且正确的执行,不会出现数据污染等意外情况。
多个线程访问同一个对象时,如果不用考虑这些线程在运行时环境下的调度和交替执行,也不需要进行额外的同步,或者在调用方进行任何其他操作,调用这个对象的行为都可以获得正确的结果,那么这个对象就是线程安全的。或者说:一个类或者程序所提供的接口对于线程来说是原子操作或者多个线程之间的切换不会导致该接口的执行结果存在二义性,也就是说我们不用考虑同步的问题。
线程安全问题大多是由全局变量及静态变量引起的,局部变量逃逸也可能导致线程安全问题。若每个线程中对全局变量、静态变量只有读操作,而无写操作,一般来说,这个全局变量是线程安全的;若有多个线程同时执行写操作,一般都需要考虑线程同步,否则的话就可能影响线程安全。类要成为线程安全的,首先必须在单线程环境中有正确的行为。如果一个类实现正确(这是说它符合规格说明的另一种方式),那么没有一种对这个类的对象的操作序列(读或者写公共字段以及调用公共方法)可以让对象处于无效状态,观察到对象处于无效状态、或者违反类的任何不可变量、前置条件或者后置条件的情况。此外,一个类要成为线程安全的,在被多个线程访问时,不管运行时环境执行这些线程有什么样的时序安排或者交错,它必须仍然有如上所述的正确行为,并且在调用的代码中没有任何额外的同步。其效果就是,在所有线程看来,对于线程安全对象的操作是以固定的、全局一致的顺序发生的。

正确性与线程安全性之间的关系非常类似于在描述 ACID(原子性、一致性、独立性和持久性)事务时使用的一致性与独立性之间的关系:从特定线程的角度看,由不同线程所执行的对象操作是先后(虽然顺序不定)而不是并行执行的。
线程安全的四中策略总结:
1.Confinement:限制可变变量共享,线程之间不共享mutable数据类型,将可变数据限制在单一进程内部,避免竞争,不让其他进程直接读写该数据。局部变量总是线程安全的,但如果局部变量是一个对象引用,若该对指向象是可变对象,则必须确定该对象也是线程confine 的,不能有其他线程也该对象的引用。
2.Immutablity不可变数据类型:使用不可变数据类型和不可变引用,避免多线程之间的竞争,不可变数据类型通常是线程安全的,如果ADT使用了可变类型,需要通过加锁机制来保证线程安全。
更强的不变性定义如下:
1.没有改变数据的操作。(不要提供setter方法等)
2.所有字段均为private和final。
3.没有表示泄露。
4.表示中的任何可变对象都不能发生变化。
5.不允许子类重写方法(直接声明为final类,或者使构造方法私有,使用工厂方法构造实例)
但是注意:如果是引用,任然必须保证指向的对象是不可变的。
3.Using Threadsafe Data Types:使用线程安全的数据类型,如果必须要使用mutable 的数据类型在多线程之间共享收据,要使用线性安全的数据类型,所有的集合类都不是线程安全的,Java提供了装饰器模式。
4.同步和锁:防止线程在同一时间访问同一数据,程序员之间负责多线程之间对mutale数据的共享操作,通过同步策略,避免多线程同时访问数据
使用锁机制。获得对数据的独家mutate权力。其他线程被阻塞,不能访问。
Monitor Pattern:用ADT之间左lock,对所有方法都加锁,把synchronized放到方法声明里和把方法体外套一个symchronized一样,Locking principle:任何共享的mutable变量必须被lock所保护,多个变量组合必须被同一个锁保护,同步机制给性能带来很大的影响。
死锁:多个线程相互竞争lock,相互等待对方释放lock
解决方案1:lock ordering。
解决方案2:使用上级对象上锁。
线程安全的意义:线程安全, 是指变量或方法( 这些变量或方法是多线程共享的) 可以在多线程的环境下被安全有效的访问。这说明了两方面的问题:
(1)可以从多个线程中调用, 无需调用方有任何操作;
(2)可以同时被多个线程调用, 无需线程之不必要的交互。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值