• Unix/Linux系统编程第四章学习笔记


    Unix/Linux系统编程第四章学习笔记

    第四章 并发编程

    4.1并行计算导论

    • Linux 环境中有很多应用程序和很多进程,其中最重要的是客户端网络/服务器。 多进程服务器是指当客户端发出请求时,服务器使用子进程来处理客户端的请求。 父进程继续等待来自其他客户端的请求。 这种方法的优点是服务器可以在客户端请求时管理客户端,特别是在交互式客户端/服务器系统中。 对于 TCP 服务器,客户端和服务器之间的连接可能不会立即关闭。 客户端发送数据后可以关闭连接。 在此期间,服务器端进程被阻塞,操作系统可能会设置其他计划。 此时的客户服务流程。 与循环服务器相比,该服务的性能得到了显着提高。

    4.1.1顺序算法与并行算法

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

    4.1.2并行性并发性

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

    4.2线程

    4.2.1线程的原理

    • 简单来说,线程是某进程同一地址空间上的独立执行单元。

    4.2.2/3线程的优点,缺点

    • 优点

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

        1.由于地址空间共享,线程需要来自用户的明确同步。
      
        2.许多库函数可能对线程不安全。通常,任何使用全局变量或依赖于静态内存内容的函数,线程都不安全。
      
        3.在单CPU系统上,使用线程解决问题实际上要比使用顺序程序慢
      

    4.3线程操作

    • 线程的执行轨迹与进程类似。线程可在内核模式用户模式下执行。
    • 内核模式:对内核进行系统调用,变为挂起、激活以继续执行等。
    • 用户模式:线程在进程的相同地址空间中执行,每个线程都有自己的堆栈。

    4.4线程管理函数

    4.4.1创建线程

    • pthread_create函数。如下:
    pthread_create(thread, attr, function, arg): create thread
    pthread_exit(status)	:	terminate thread
    pthread_cancel(thread)	:	cancel thread
    pthread_attr_init(attr)	:	initialize thread attributes
    pthread_attr_destroy(attr):     destroy thread attribute
    
    

    4.4.2线程ID

    • 一种不透明的数据类型,取决于实现情况
    int pthread_equal(pthread_t t1, pthread_t t2);//比较线程ID
    

    4.4.3线程终止

    • 线程函数结束后,即终止。
    void pthread_exit(void *status);//返回值:0退出值表示正常终止,非0值表示异常终止
    

    4.4.4线程连接

    int pthread_join(pthread_t thread, void **status_ptr);//终止线程的退出状态以status_ptr返回
    

    4.5线程实例程序(实践内容放在了篇尾)

    4.6线程同步

    • 当多个线程试图修改同一共享变量或数据结构时,如果修改结果取决于线程的执行顺序,则称之为竞态条件。在并发程序中,绝不能有竞态条件。

    4.6.1互斥量

    • 在Pthread中,互斥量也被称为“”,意为互相排斥。允许执行实体仅在有锁的情况下才能继续执行的同步工具。
    • 静态方法:
    pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER
    
    
    • 动态方法:使用pthread_mutex_init()函数

    4.6.2死锁预防

    • 互斥量使用封锁协议,如果某线程不能获取互斥量,就会被阻塞,等待互斥量解锁后再继续,然后死锁就发生了,死锁是一种状态,许多执行实体相互等待,都无法继续下去。
    • 有多种方法可以解决死锁问题:死锁预防死锁规避死锁检测和恢复等。

    4.6.3条件变量

    • 提供了一种线程协作的方法
    • 静态方法:
    pthread_cond_t con = PTHREAD_COND_INITIALIZER
    
    • 动态方法:使用pthread_cond_init()函数

    4.6.5信号量

    • 是一种数据结构,必须使用一个初始值和一个空等队列进行初始化。从执行实体的角度来看,对信号量的操作都是原子操作基本操作

    4.6.6屏障

    • 线程连接操作允许某线程等待其他线程终止,在Pthread中,可以采用的机制是屏障以及一系列屏障函数。

    4.6.8Linux中的线程

    • Linux不区分线程和进程,它们都是由clone()系统调用创建的。

    示例实践(4.5相关)

    • 计算一个N X N矩阵元素的和
    • 代码:
    #include <stdio.h>
    #include <stdlib.h>
    #include <pthread.h>
    #define N 4
    int A[N][N],sum[N];
    
    void *func(void *arg)
    {
            int j,row ;
            pthread_t tid = pthread_self();
            row = (int)arg;
            printf("Thread %d [%lu] computes sum of row %d\n",row,tid,row);
            for(j=0;j<N; j++)
                    sum[row] += A[row][j];
            printf("Thread %d [%lu] done:sum [%d] =%d\n",row,tid,row,sum[row]);
            pthread_exit ((void*)0);
    }
            int main(int argc, char *argv[])
    {
            pthread_t thread[N];
            int i,j,r,total = 0;
            void *status;
            printf("Main: initialize A matrix\n");
            for(i=0; i<N;i++){
                    sum[i] = 0;
                    for(j=0;j<N;j++){
                            A[i][j]=i*N+j+1;
                            printf("%4d ",A[i][j]);
                    }
                    printf( "\n" );
            }
            printf ("Main: create %d threads\n",N);
            for(i=0;i<N;i++) {
                    pthread_create(&thread[i],NULL,func,(void *)i);
            }
            printf("Main: try to join with thread\n");
            for(i=0; i<N; i++) {
                    pthread_join(thread[i],&status);
                    printf("Main: joined with %d [%lu]: status=%d\n",i,thread[i],
                                    (int)status);
            }
            printf("Main: compute and print total sum:");
            for(i=0;i<N;i++)
                    total += sum[i];
            printf ("tatal = %d\n",total );
            pthread_exit(NULL);
    }
    
    
    • 运行结果:
  • 相关阅读:
    对于 redux 的一些理解-1.基础
    css 优化
    HTML 理解标签
    css 理解盒模型
    json2.js JSON解析程序
    DOM 核心
    居中
    Director.js
    jquery-2.0.3 源码分析 整体架构
    Zookeeper安装
  • 原文地址:https://www.cnblogs.com/wdys12138/p/16792079.html
Copyright © 2020-2023  润新知