zoukankan      html  css  js  c++  java
  • 【软件构造】课程提纲(7)

    第十章

    1. 进程和线程:两种不同的并发模块

    (1)进程:正在运行程序的一个实例,拥有自己私有专用的内存空间

      ·可抽象为虚拟计算机,拥有独立的执行环境和完整的资源

      ·进程间通常不共享内存,不能访问其他进程的内存和对象,需要特殊机制

      ·进程通信采用消息传递方式,即标准I/O流,为了实现进程间通信,大多数操作系统都支持“进程间通信(IPC)资源”,如管道和socket

    (2)线程:正在运行程序的一个执行路径(一个进程可对应多个线程)

      ·线程有自己的堆栈和局部变量,但是多个线程共享内存空间

      ·可抽象为一个虚拟处理器,有时也称为轻量级进程

      ·线程存在于进程内,与进程中的其他线程共享相同的资源

      ·采用内存共享机制通信,需要特殊处理才能实现消息传递和私有内存

    2. 线程的创建和启动、runnable

    (1)所有的线程都需要实现Runnable接口,在run()中写具体实现

       

    2创建Thread子类型

       

    3)提供一个Runnable对象

       

    4)惯用法:用一个匿名的Runnable启动一个线程,避免创建命名类

       

    3. 时间分片、交错执行、竞争条件

    (1)时间分片

      ·在某时刻,一个运行核心上只有一个线程可以运行

      ·当线程数多于处理器数量时,并发性通过时间片来模拟,处理器切换处理不同的线程

    (2)交错执行:时间片的使用不可预知且非确定,线程可能随时暂停或恢复

     

    (3)竞争条件:程序的正确性(后置条件和不变量的满足)取决于并发计算AB中事件的相对时间,例如AB都需要从银行中取走全部存款,A取走时B可能不知道,导致了没有足够的存款,产生竞争

    4. 线程的休眠、中断

    (1)休眠

      ·sleep():让当前线程暂停指定时间的执行

      ·join():确保当前线程能够执行完毕

      ·wait():释放锁,让线程进入等待,直到调用notify()

    (2)中断(interrupt

      ·每个线程都有中断状态,初始为false

      ·若该线程在执行低级可中断阻塞方法,取消阻塞,抛出中断异常,否则设置中断状态为true

      ·在被中断线程中运行的代码以后可以轮询中断状态,看看它是否被请求停止正在做的事情

      ·当一个线程中断另一个线程时,被中断的线程不一定要立即停止,只需在愿意并且方便的时候停止,为安全地构造可取消活动提供了更大的灵活性

      ·如果活动在正在进行更新的时候被取消,那么程序数据结构可能处于不一致状态,中断允许一个可取消活动来清理正在进行的工作,恢复不变量,通知其他活动它要被取消,然后才终止

    5. 线程安全:无论如何执行,不许调度者做额外的协作,都能满足正确性

    (1)Confinement:限制可变变量的共享

      ·将数据限制在单个线程中,避免线程在可变数据上进行竞争

      ·局部变量保存在线程栈中,每个调用都有自己的变量副本,如果是对象的引用,则要确保不能引用任何其他线程可访问的对象

      ·在多线程环境中,取消全局变量,尽量避免使用不安全的静态变量

    (2)Immutability:用不可变的共享变量

      ·解决了因为共享可变数据造成的竞争,可以安全地从多个线程访问final

      ·这种安全性只适用于变量本身,仍需确保变量指向的对象是不可变的

      ·如果类型的对象在整个生命周期中表示相同的抽象值,则类型不可变

      ·若改变对用户不可见,且对应抽象值不变,允许对rep进行更改

      ·不变性的强定义

        - 没有改变数据的操作

        - 所有字段均为privatefinal

        - 没有表示泄露

        - 表示中的任何可变对象都不能变化

        - 不存储传递给构造函数的外部可变对象的引用

        - 避免在方法返回值中包含对可变对象的引用

    (3)Threadsafe data type:将共享数据封装在线程安全的数据类型中

      ·如ListSetMap等数据结构是不安全的,线程安全提供了Connections的类型,可确保方法是原子的(动作的内部操作不会同其他操作交叉,不会产生部分完成的情况),例:private static Map<Integer,Boolean> cache = Collections.synchronizedMap(new HashMap<>());    

      ·统一采用包装类的形式,确保抛弃对底层非线程安全容器类的引用

      ·迭代器仍然不安全,在迭代collection的时候需获取集合的锁

      ·原子操作仍然不足以完全避免竞争,如检查集合是否为空的时候,另一个线程可能提前取走了元素

      ·包装的实现是将所有的实际工作委托给指定的容器,但在容器的基础上添加额外的功能

    (4)Synchronization:使用同步来防止线程同时访问变量

      ·锁是一种实现同步的抽象,某一时刻最多允许一个线程拥有锁

      ·锁的两种操作

        - 获取锁的所有权:如过锁被其他线程拥有,将进入阻塞状态,等待锁释放后再同其他线程竞争

        - 释放锁的所有权

      ·使用锁可以确保锁的所有者始终查看最新的数据

      ·锁只能确保与其他请求获取相同对象锁的线程互斥访问,若其他线程采用不同的锁,则同步失效

      ·当线程调用同步方法时,它会自动获取该方法对象的内部锁,并在方法返回时释放它。即使返回是由未捕获的异常引起的,也会释放锁

      ·同一对象上的同步方法的两次调用不会有交错现象

    6. Message passing

    (1)各个处理模块间通过信息传递来进行交互

    (2)接收方将收到的消息形成队列逐一处理,消息发送者继续发送(异步方式)

    (3)并不能消除竞争条件的可能性

    (4)选择模型时,withdraw-if-sufficient-funds比单纯的withdraw更合适

    7. 死锁

    (1)由于使用锁需要线程等待,可能会陷入两个线程正在等待对方,陷入永远阻塞的情况

    (2)死锁可能涉及两个以上的模块,线程间的依赖关系环是出现死锁的信号

    (3)防止死锁方法

      ·对需要同时获取的锁进行排序,并确保所有代码按照该顺序获取锁定,例:

       

      ·用单个粗粒度的锁监控多个对象实例(但性能损失大)

    8. 以注释的形式撰写线程安全策略

    1)需要对安全性进行这种仔细的论证,阐述使用了哪种技术,使用threadsafe data types, or synchronization时,需要论证所有对数据的访问都是具有原子性的

    2)例:

       

    3)反例:

       

  • 相关阅读:
    5.3二叉树的运算
    hadoop namenode切换
    org.apache.hadoop.security.AccessControlException
    Hive中的日志
    命令大全详解
    python深浅copy
    awk命令
    head&tail命令
    cut命令
    理解inode
  • 原文地址:https://www.cnblogs.com/zhangyushuqing/p/9192493.html
Copyright © 2011-2022 走看看