zoukankan      html  css  js  c++  java
  • 软件构造 并发3(线程安全性)

    线程安全:数据类型或静态方法在多线程中执行时,无论如何执行,不需调用者做额外的协作仍可以得到正确的行为。

                     行为正确意味着满足规格说明和保持不变性   不能在前置条件中对调用者增加时间性要求(在set()运行时不能调用get())

                     例子:迭代器, 不是线程安全的。 迭代器的规范说,不能在迭代它的同时修改一个集合。 这是一个与调用者相关的时间相关的前提条件,如果违反它,Iterator不保证行为正确

    线程安全的四个方法:①限制可变变量的共享②用不可变的共享变量③将共享数据封装在线程安全的数据类型中④使用同步来防止线程同时访问变量

    限制可变变量的共享:通过将数据限制在单个线程中,可以避免线程在可变数据上进行竞争。可变量的共享是竞争的主要原因

                                       ①局部变量保存在线程栈中,每个调用都有自己的变量副本 ,每个线程都有自己的堆栈。

                                       ②局部变量如果是对象的引用,则要确保不能引用任何其他线程可访问 的对象。

                                       避免全局变量:全局静态变量不会自动受到线程访问限制。如果使用了全局静态变量,应说明只有一个线程会使用它们。最好在多线程环境中取消全局静态变量

                                       两个线程若同时调用一个返回类的公众静态方法,会产生两个实例,破坏了表示不变性。改造:采用限制的方式并自行确保只有一个线程访问该方法;采用synchronized方式

                                       HashMap也不是线程安全的

    用不可变的共享变量:使用不可变的引用和数据类型。不可变解决了因为共享可变数据造成的竞争,并简单地通过使共享数据不可变来解决它。

                                        final变量是不可变的引用,所以声明为final的变量可以安全地从多个线程访问。(只能读不能写   因为这种安全性只适用于变量本身,仍然必须确保变量指向的对象是不可变的)

                                       回忆不变性:类型是不可变的:如果类型的对象在其整个生命周期中始终表示相同的抽象值

                                                             但实际上,允许对rep进行改变,只要这些改变对客户是不可见的,并且对应的抽象值不变(有益的突变)但是对于并发性,这种隐藏的变化是不安全的 , 使用有益的变  

                                                             化的不可变数据类型必须使用锁使自己线程安全。

    将共享数据封装在线程安全的数据类型中与不安全类型相比,线程安全数据类型通常会导致性能损失

                                                                          线程安全的集合(Collections)List Set Map ArrayList HashMap HashSet都不是线程安全的

                                                                          java提供了线程安全的Collections类版本:方法是原子的,(原子方法:动作的内部操作不会同其他操作交叉,不会产生部分完成的情况)

                                                                                                                                                 private static Map<Integer,Boolean> cache =  Collections.synchronizedMap(new HashMap<>());

                                                                                                                                                 新的HashMap只传递给synchronizedMap,并且永远不会存储 在其他地方。

                                                                          迭代器也不是线程安全的:使用iterator()或for循环语法也是不安全的,在需要迭代它时获取集合的锁。原子 操作不足以完全防止竞争
                                                                          线程安全包装:

    通过共享可变数据的竞争条件实现安全的三种主要方式:①限制可变变量的共享②用不可变的共享变量③将共享数据封装在线程安全的数据类型中

                     

  • 相关阅读:
    SQL Server存储过程
    数据访问模式:数据并发控制(Data Concurrency Control)
    C#设计模式系列:观察者模式(Observer)
    awk内置字符串函数 awk 格式化输出
    使用MegaCli和Smartctl获取普通磁盘
    Shell之date用法
    linux 系统下查看raid信息,以及磁盘信息
    linux下proc里关于磁盘性能的参数
    hdparm测试硬盘性能
    查看现有运行的linux服务器有多少内存条
  • 原文地址:https://www.cnblogs.com/xgl122/p/9196640.html
Copyright © 2011-2022 走看看