线程安全:数据类型或静态方法在多线程中执行时,无论如何执行,不需调用者做额外的协作仍可以得到正确的行为。
行为正确意味着满足规格说明和保持不变性 不能在前置条件中对调用者增加时间性要求(在set()运行时不能调用get())
例子:迭代器, 不是线程安全的。 迭代器的规范说,不能在迭代它的同时修改一个集合。 这是一个与调用者相关的时间相关的前提条件,如果违反它,Iterator不保证行为正确
线程安全的四个方法:①限制可变变量的共享②用不可变的共享变量③将共享数据封装在线程安全的数据类型中④使用同步来防止线程同时访问变量
限制可变变量的共享:通过将数据限制在单个线程中,可以避免线程在可变数据上进行竞争。可变量的共享是竞争的主要原因
①局部变量保存在线程栈中,每个调用都有自己的变量副本 ,每个线程都有自己的堆栈。
②局部变量如果是对象的引用,则要确保不能引用任何其他线程可访问 的对象。
避免全局变量:全局静态变量不会自动受到线程访问限制。如果使用了全局静态变量,应说明只有一个线程会使用它们。最好在多线程环境中取消全局静态变量
两个线程若同时调用一个返回类的公众静态方法,会产生两个实例,破坏了表示不变性。改造:采用限制的方式并自行确保只有一个线程访问该方法;采用synchronized方式
HashMap也不是线程安全的
用不可变的共享变量:使用不可变的引用和数据类型。不可变解决了因为共享可变数据造成的竞争,并简单地通过使共享数据不可变来解决它。
final变量是不可变的引用,所以声明为final的变量可以安全地从多个线程访问。(只能读不能写 因为这种安全性只适用于变量本身,仍然必须确保变量指向的对象是不可变的)
回忆不变性:类型是不可变的:如果类型的对象在其整个生命周期中始终表示相同的抽象值
但实际上,允许对rep进行改变,只要这些改变对客户是不可见的,并且对应的抽象值不变(有益的突变)但是对于并发性,这种隐藏的变化是不安全的 , 使用有益的变
化的不可变数据类型必须使用锁使自己线程安全。
原文地址:https://www.cnblogs.com/xgl122/p/9196640.html