第四章学习笔记

AI提问

1.线程与进程的联系 在这里插入图片描述

在这里插入图片描述

2.API

在这里插入图片描述

3.线程管理的API对于线程有什么作用

在这里插入图片描述
在这里插入图片描述

4.如何创建线程

在这里插入图片描述
在这里插入图片描述在这里插入图片描述
在这里插入图片描述

5.线程互斥量

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

学习笔记

一、并行计算导论

1、并行计算是一种计算方案,它尝试使用多个执行并行算法的处理器解决问题。

2、顺序算法与并行算法:

(1)、描述顺序算法常用begin end代码块列出算法:
begin
	step_1;
	step_2;
	...
	step_n;
end
// next step

所有步骤都是通过单个任务依次执行的,每次执行为一个步骤。所有步骤执行完成,算法结束。

(2)、并行算法,使用cobegin-coend代码块来指定并行算法的独立任务。
:cobegin
	task_1;
	task_2;
	...
	task_n;
coend
// next step

在cobegin-coend代码块里,所有的任务都是并行执行的,cobegin-coend代码块的下一步骤将在所有任务完成之后执行。

二、线程

1.介绍:线程是与进程共享地址空间的独立执行单元,同时,线程也与进程共享其他资源。线程可以创建与自己共享地址的子线程,子线程也可再创建自己的子线程,进程就是通过它的主线程和子线程实现任务处理的。不同的操作系统实现线程的方式不尽相同,但目前几乎所有的操作系统都支持IEEE POSIX 1003.1的线程标准Pthread。

2.优缺点:

优: 创建和切换速度更块 响应速度更快 更适合并行计算 缺: 需要来自用户的明确同步 库函数对于线程来说不够安全
单CPU系统中上下文切换耗时过大

3.线程操作:线程可在用户模式或内核模式下执行,在用户模式下,线程在进程的相同地址空间里执行。

4.线程管理函数:

pthread_create(thread, attr, function, arg);	-> 创建线程
pthread_exit(status);			           -> 终止线程
pthread_cancel(thread);                     -> 取消线程
pthread_attr_init(attr);                    -> 初始化线程属性
pthread_attr_destroy(attr);                 -> 删除线程属性

5.创建线程:

使用pthread_create()函数创建线程:
int pthread_create(pthread_t *pthread_id, pthread_attr_t *atr, void *(*func)(void *), void *arg);
创建成功返回0,反之返回错误代码;
pthread_create()函数参数:

(1)、pthread_id是指向pthread_t类型变量的指针。它会被操作系统内核分配的唯一线程ID填充。在POSIX中,pthread_t是一种不透明的类型.线程可以通过pthread_self()函数获得自己的ID。在Linux中,pthread_t类型被定义为无符号长整型,因此ID可以打印为%lu。
(2)、attr是指向另一种不透明数据类型的指针,它指向线程属性。 (3)、func是要执行的新线程函数的入口地址。
(4)arg指向线程函数参数的指针:void *func(void *arg);
注:attr参数较复杂,下为attract参数使用步骤: ① 定义一个pthread属性变量pthread_attr_t attr
② 用pthread_attr_init(&attr)初始化属性变量。 ③ 设置属性变量并在pthread_create()调用;
④ 必要时,通过pthread_attr_destroy(&attr)释放attr资源

6.线程ID,是一种不透明的数据类型,不应该直接比较线程ID,如果需要,可使用int pthread_equal (pthread_t t1,pthread_t t2)进行比较。相同返回0,反之返回非0.

7.线程终止:线程函数结束之后线程即终止,或者使用:

int pthread_exit (void *status);
进行显示终止,0表示正常终止,非0异常。

8.线程连接:

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

三、线程同步

1.线程在进程的同一地址空间中执行,共享同一地址空间中的所有全局变量和数据结构。不同的线程对同一个共享资源进行操作时,如果结果取决于线程的执行顺序,就会产生竞争,这是并发程序所杜绝的。

2.互斥量:为了解决线程间的竞争,可以使用互斥量。它是一个锁,当拥有锁的时候才可以进行操作。互斥量可以通过静态和动态两种方式初始化。当一个线程需要访问共享资源时,它必须首先获得互斥量的所有权。如果互斥量已经被另一个线程拥有,那么尝试获取所有权的线程将被阻塞,直到拥有互斥量的线程释放它。这概念就像是一把锁,一个线程需要锁定(或者说拥有)互斥量才能访问共享资源,当它完成后,它需要解锁(或者说释放)互斥量,以便其他线程可以获得互斥量并访问共享资源。

3.死锁预防:互斥量采用了封锁协议,如果线程无法获取互斥量,那么就会被阻塞,等待互斥量解锁后才能继续操作。当多个实体互相等待时,死锁就会出现。应对方法有死锁预防、死锁规避、死锁检测和恢复等。预防死锁可以通过条件加锁函数pthread_mutex_trylock()实现。

4.条件变量:条件变量可以实现线程间协作

三 ,实践

用并发线程快速排序

/* * * chapter4 code example 4.2 QUICK SORT * * */
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
typedef struct{
        int upperbound;
        int lowerbound;
}PARM;
#define N 10
int a[N] = {2,1,3,4,6,5,8,7,9,0};       //unsorted data
int print()     //print current A[] contents
{
        int i;
        printf("[ ");
        for(i = 0 ; i < N ; i++)
                printf("%d" , a[i]);
        printf("]\n");
}
void *Qsort(void *aptr)
{
        PARM *ap , aleft , aright;
        int pivot , pivotIndex , left ,right ,temp;
        int upperbound , lowerbound;

        pthread_t me , leftThread , rightThread;
        me = pthread_self();
        ap =(PARM *)aptr;
        upperbound = ap->upperbound;
        lowerbound = ap->lowerbound;
        pivot = a[upperbound];          //pick low pivot value
        left = lowerbound - 1;          //scan index from left side
        right = upperbound;             //scan index from right side
        if(lowerbound >= upperbound)
                pthread_exit (NULL);
        while(left < right){            //partition loop
                do{left++;} while (a[left] < pivot);
                do{right--;}while(a[right] > pivot);
                if (left < right ) {
                        temp = a[left]; a[left] = a[right]; a[right] = temp;
                }
        }
        print();
        pivotIndex = left;              //put pivot back
        temp = a[pivotIndex] ;
        a[pivotIndex] = pivot;
        a[upperbound] = temp;
        //start the "recursive threads"
        aleft.upperbound = pivotIndex - 1;
        aleft.lowerbound = lowerbound;
        aright.upperbound = upperbound;
        aright.lowerbound = pivotIndex + 1;
        printf("%lu: create left and right threadsln", me) ;
        pthread_create(&leftThread , NULL , Qsort , (void * )&aleft);
        pthread_create(&rightThread , NULL , Qsort , (void *)&aright);
        //wait for left and right threads to finish
        pthread_join(leftThread,NULL);
        pthread_join(rightThread, NULL);
        printf("%lu: joined with left & right threads\n",me);
}
int main(int argc, char *argv[]){
        PARM arg;
        int i, *array;
        pthread_t me,thread;
        me = pthread_self( );
        printf("main %lu: unsorted array = ", me);
        print( ) ;
        arg.upperbound = N-1;
        arg. lowerbound = 0 ;
        printf("main %lu create a thread to do QS\n" , me);
        pthread_create(&thread , NULL , Qsort , (void * ) &arg);
        //wait for qs thread to finish
        pthread_join(thread,NULL);
        printf ("main %lu sorted array = ", me);
        print () ;
}                                    

运行

在这里插入图片描述

课本结果:
在这里插入图片描述

苏格拉底提问

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值