zoukankan      html  css  js  c++  java
  • 第四章学习笔记

    一、概要:

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

    二、学到了什么

    1. 并行性与并发性

    通常,并行算法只识别可并行执行的任务,但是它没有规定如何将任务映射到处理组件。在理想情况下,并行算法中的所有任务都应该同时实时执行。然而,真正的并行执行只能在有多个处理组件的系统中实现,比如多处理器或多核系统。在单 CPU 系统中,一次只能执行一个任务。在这种情况下,不同的任务只能并发执行、即在逻辑上并行执行。在单CPU系统中,并发性是通过多任务处理来实现的,该内容已在第3章中讨论过。在本章的最后,我们将在一个编程项目中再次讲解和示范多任务处理的原理和方法。

    1. 线程

    (1)线程的原理

    线程是某进程同一地址空间上的独立执行单元。创建某个进程就是在一个唯一地址空间创建一个主线程。当某进程开始时,就会执行该进程的主线程。如果只有一个主线程,那么进程和线程实际上并没有区别。但是,主线程可能会创建其他线程。每个线程又可以创建更多的线程等。

    (2)线程的优点

    线程创建和切换速度更快;

    线程的相应速度更快;

    线程更适合并行计算;

    (3)线程的缺点

    (1)由于地址空间共享,线程需要来自用户的明确同步。

    (2)许多库函数可能对线程不安全,例如传统 strtok()函数将一个字符串分成一连串令牌。通常,任何使用全局变量或依赖于静态内存内容的函数,线程都不安全。为了使库函数适应线程环境,还需要做大量的工作。

    (3)在单 CPU系统上,使用线程解决问题实际上要比使用顺序程序慢,这是由在运行时创建线程和切换上下文的系统开销造成的。

    1. 线程管理函数

    (1)创建线程

    使用pthread_create()函数创建线程。

    int prhread_create (pthread_t *pthread_id,pthread_attr_t *attr,
    
    Void *(*func)(void *), void *arg);
    

    如果成功则返回0,如果失败则返回错误代码。

    其中,attr参数最复杂。下面给出了 attr参数的使用步骤。

    1.定义一个pthread属性变量 pthread_attr_t attr。

    2.用pthread_attr_init(&attr)初始化属性变量。

    3.设置属性变量并在 pthread_create()调用中使用。

    4.必要时,通过 pthread_attr_destroy(&attr)释放 attr资源。

    4.线程同步

    (1)互斥量

    1.一种是静态方法:

    pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER
    

    定义互斥量m,并使用默认属性对其进行初始化。

    2.一种是动态方法:使用pthread_mutex_init()函数,可通过attr参数设置互斥属性。

    pthread_mutex_init(pthread_mutex_t *m,pthread_mutexattr_t,*attr);
    

    (2)死锁预防

    有多种方法可以解决可能的死锁问题,其中包括死锁预防、死锁规避、死锁检测和恢复等。在实际系统中,唯一可行的方法是死锁预防,试图在设计并行算法时防止死锁的发生。一种简单的死锁预防方法是对互斥量进行排序,并确保每个线程只在一个方向请求互斥量,这样请求序列中就不会有循环。

    但是,仅使用单向加锁请求来设计每个并行算法是不可能的。在这种情况下,可以使用条件加锁函数 pthread mutex trylock(来预防死锁。如果互斥量已被加锁,则 trylock(函数会立即返回一个错误。在这种情况下,调用线程可能会释放它已经获取的一些互斥量以便进行退避,从而让其他线程继续执行。在上面的交叉加锁示例中,我们可以重新设计其中一个线程,

    避免死锁-利用银行家算法避免死锁。

    实践与代码

    例4.1:用线程计算矩阵的和

    假设计算一各N*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
    ",row,tid,row);
    
    for(j=0;j<N; j++)
    
    sum[row] += A[row][j];
    
    printf("Thread %d [%lu] done:sum [%d] =%d
    ",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
    ");
    
    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( "
    " );
    
    }
    
    printf ("Main: create %d threads
    ",N);
    
    for(i=0;i<N;i++) {
    
    pthread_create(&thread[i],NULL,func,(void *)i);
    
    }
    
    printf("Main: try to join with thread
    ");
    
    for(i=0; i<N; i++) {
    
    pthread_join(thread[i],&status);
    
    printf("Main: joined with %d [%lu]: status=%d
    ",i,thread[i],
    
    (int)status);
    
    }
    
    printf("Main: compute and print total sum:");
    
    for(i=0;i<N;i++)
    
    total += sum[i];
    
    printf ("tatal = %d
    ",total );
    
    pthread_exit(NULL);
    
    }
    

    遇到的问题:

    在试用Linux 线程模块时,试用pthread_create 函数。

    编译命令为 gcc test.c -o test时,会出现如下错误

    解决办法:
    在gcc编译的时候,附加要加 -lpthread参数即可解决。

    试用如下命令即可编译通过:gcc test.c -o test -lpthread

  • 相关阅读:
    nginx负载均衡集群
    pureftp 服务
    LVS集群之DR模式 实现
    LVS集群之NAT模式实现
    resin 安装配置
    nfs部署和优化
    电压和电流有什么关系
    自动循环播放 播放器
    有趣的匿名方法
    使用匿名委托,Lambda简化多线程代码
  • 原文地址:https://www.cnblogs.com/Werido-/p/15490121.html
Copyright © 2011-2022 走看看