• 学习笔记7


    第四章 并发编程

    教材学习内容总结

    本章论述了并发编程,介绍了并行计算的概念,指岀了并行计算的重要性;比较了顺序 算法与并行算法,以及并行性与并发性;解释了线程的原理及其相对于进程的优势;通过示 例介绍了 Pthread中的线程操作,包括线程管理函数,互斥量、连接、条件变量和屏障等线 程同步工具;通过具体示例演示了如何使用线程进行并发编程,包括矩阵计算、快速排序和 用并发线程求解线性方程组等方法;解释了死锁问题,并说明了如何防止并发程序中的死锁 问题;讨论了信号量,并论证了它们相对于条件变量的优点;还解释了支持Linux中线程的 独特方式。编程项目是为了实现用户级线程。它提供了一个基础系统来帮助读者开始工作。 这个基础系统支持并发任务的动态创建、执行和终止,相当于在某个进程的同一地址空间中 执行线程。读者可通过该项目实现线程同步的线程连接、互斥量和信号量,并演示它们在并 发程序中的用法,该编程项目会让读者更加深入地了解多任务处理、线程同步和并发编程的 原理及方法。

    1. 并行

    **1.顺序算法和并行算法

    ·顺序算法:begin-end代码块列出算法。可包含多个步骤,所有步骤通过单个任务依次执行,每次执行一个步骤,全执行完,算法结束。
    ·并行算法:cobegin-coend代码块来指定独立任务,所有任务都是并行执行的,紧接着代码块的下一个步骤将只在所有这些任务完成之后执行。

    2.并行行与并发性
    通常,并行算法只识别可并行执行的任务,但是它没有规定如何将任务映射到处理组件。在理想情况下,并行算法中的所有任务都应该同时实时执行。然而,真正的并行执行只能在有多个处理组件的系统中实现,比如多处理器或多核系统。在单 CPU 系统中,一次只能执行一个任务。在这种情况下,不同的任务只能并发执行、即在逻辑上并行执行。在单CPU系统中,并发性是通过多任务处理来实现的。

    2.线程

    1.原理

    • 线程是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。在Unix System V及SunOS中也被称为轻量进程(lightweight processes),但轻量进程更多指内核线程(kernel thread),而把用户线程(user thread)称为线程。
      线程是独立调度和分派的基本单位。线程可以为操作系统内核调度的内核线程,如Win32线程;由用户进程自行调度的用户线程,如Linux平台的POSIX Thread;或者由内核与用户进程,如Windows 7的线程,进行混合调度

    • 同一进程中的多条线程将共享该进程中的全部系统资源,如虚拟地址空间,文件描述符和信号处理等等。但同一进程中的多个线程有各自的调用栈(call stack),自己的寄存器环境(register context),自己的线程本地存储(thread-local storage)。
      一个进程可以有很多线程,每条线程并行执行不同的任务。

    • 在多核或多CPU,或支持Hyper-threading的CPU上使用多线程程序设计的好处是显而易见,即提高了程序的执行吞吐率。在单CPU单核的计算机上,使用多线程技术,也可以把进程中负责I/O处理、人机交互而常被阻塞的部分与密集计算的部分分开来执行,编写专门的workhorse线程执行密集计算,从而提高了程序的执行效率。

    2.优点
    type.h 文件定义了系统常数和表示进程的简单 PROC结构体。

    1. 线程创建和切换速度更快。
    2. 线程的响应速度更快。
    3. 线程更适合并行计算。

    3.缺点

    1. 由于地址空间共享,线程需要来自用户的明确同步。
    2. 许多库函数可能对线程不安全。
    3. 在单CPU系统上,使用线程解决问题实际上要比使用顺序程序慢,这是由在运行 时创建线程和切换上下文的系统开销造成的。

    3.线程管理函数

    1.创建线程
    使用pthread_create()函数创建线程

    int pthread_create(pthread_t *thread, const pthread_attr_t *attr,void *(*start_routine) (void *), void *arg);
    

    2. 线程ID

    使用pthread_equal()函数对线程ID进行比较

    int pthread_equal(pthread_t t1,pthread_t t2);
    返回值:不同线程返回0,否则返回非0
    

    3.线程终止
    线程可以调用函数进行终止

    void pthread_exit(void *status);
    返回值:0退出值表示正常终止,非0值表示异常终止
    

    4.线程连接
    一个线程可以等待另一个线程的终止,通过函数终止线程的退出状态。

    int pthread_join (pthread_t thread, void **status ptr);
    返回值:以status_ptr返回
    

    4.线程同步

    同步是一种机制和规则,用于确保共享数据对象的完整性和并发执行肢体的协调性。
    1.互斥量
    最简单的同步工具时锁,它允许执行实体仅在有锁的情况下才能继续执行。在Pthread中,锁被称为互斥量。在使用前必须对他们进行初始化。
    (1)静态方法
    (2)动态方法
    通常attr参数可以设置位NULL,作为默认属性。

    初始化完成后,线程可以通过以下函数使用互斥量。

    线程使用互斥量来保护共享数据对象。

    互斥量的典型用法
    线程先创建一个互斥量并对它进行依次初始化。新创建的互斥量处于解锁状态,没有所有者。每个线程都试图访问一个共享数据对象:

    只有获取了互斥量的线程才能访问共享数据对象。

    2. 死锁预防

    互斥量使用封锁协议。有多种方法可以解决可能的死锁问题,其中包括死锁防御、死锁规避、死锁检测和回复等。在实际情况中,唯一可行的方法时死锁预防,试图在设计并行算法是防止死锁发生。

    一种简单的死锁预防时对互斥量进行排序,并确保每个线程只在一个方向请求互斥量,这样请求序列中就不会有循环。

    条件加锁和退避预防死锁

    3.条件变量

    作为锁,互斥量仅用于确保线程只能互斥地访问临界区中的共享数据对象。条件变量提供了一种线程协作的方法。在Pthread中,使用othread_cond_t来声明条件变量,而且必须在使用前进行初始化。
    (1) 静态方法

    (2) 动态方法

    4.信号量

    信号量是进程同步的一般机制。(计数)信号量是一种数据结构

    struct sem{

    int value;

    struct process *queue

    }s;

    最有名的信号量操作时P和V,定义见下文。

    5.屏障
    线程连接操作允许某线程(通常是主线程)等待其他线程终止。在某些情况下,保持线程活动会更好,但应要求他们在所有线程都达到指定同步点之前不能继续活动。在Pthreads中,可以采用屏障以及一系列屏障函数。

    首先,主线程创建一个屏障对象

    pthread_barrier_init(&barrier NULL,nthreads);
    

    用屏蔽中同步线程数字对他进行初始化。然后,主线程创建工作线程来执行任务。

    **6.linux中的线程
    与其他操作系统不同,Linux不区分进程和线程。对于Linux内核,线程只是一个与其他进程共享某些资源的进程。在Linux中,进程和线程都是由clone()系统调用创建的。

    int clone(int(*fn)(void *),void *chile_stack,int flags,void *arg)
    
  • 相关阅读:
    Linux笔记(九)
    Linux笔记(八)
    Linux笔记(七)
    Linux笔记(五)
    Linux笔记(六)
    Linux笔记(四)
    Linux笔记(三)
    hdu 1009 qsort运用
    dfs模板 二部图的最大匹配
    拉格朗日函数c++
  • 原文地址:https://www.cnblogs.com/marryj/p/16787873.html
Copyright © 2020-2023  润新知