OS之进程管理---多线程模型和线程库(POSIX PTread)
2021-05-06 10:29
标签:路径 load 名称 更新 als 机器 获得 初始 最简 转自 https://www.cnblogs.com/lishanlei/p/10707749.html 多线程的背景:传统进程是单线程结构进程,单线程结构进程在并发程序设计上存在进程切换开销大、进程通信开销大、限制了进程并发的粒度、降低了并行计算的效率等问题。 解决问题的思路: 把进程的两项功能,即“独立分配资源”与“被调度分派执行”分离开来; 进程作为系统资源分配和保护的独立单位,不需要频繁地切换; 线程作为系统调度和分派的基本单位,能轻装运行,会被频繁地调度和切换; 线程的出现会减少进程并发执行所付出的时空开销,使得并发粒度更细、并发性更好 进程要支撑线程运行,为线程提供虚拟地址空间和各种资源,它具有: 一个独立的虚拟地址空间,用来容纳进程映像 以进程为单位对各种资源,如文件、I/O设备等实施保护 线程是是调度的基本单位。它是进程的一条执行路径,同一个进程中的所有线程共享进程获得的主存空间和资源,它具有: 线程执行状态 受保护的线程上下文,当线程不运行时,用于存储现场信息 独立的程序指令计数器 执行堆栈 容纳局部变量的静态存储器 线程是CPU使用的基本单元,包括线程ID,程序计数器、寄存器组、各自的堆栈等,在相同线程组中,所有线程共享进程代码段,数据段和其他系统资源。 有两种方法来提供线程的支持:用户层的用户线程(User-Level Thread)、内核层的内核线程(Kernel-Level Thread)。 用户线程和内核线程之间存在三种关联方式:多对一模型、一对一模型、多对多模型。 多对一模型映射多个用户级线程到一个内核线程。线程管理是由用户空间的线程库来完成的,所以效率挺高。但是,如果一个线程执行阻塞系统调用,那么整个进程将会阻塞。另外,因为任一时间只有一个线程可以访问内核,所以多个线程不能运行在多核系统上,现在已经几乎没有操作系统来使用这个模型了,因为它无法利用多个处理核。 一对一模型映射每个用户线程到一个内核线程。该模型在一个线程执行阻塞系统调用时,能够允许另外一个线程继续执行,所以它提供了比多对一模型更好的并发功能。它页允许多个线程并行运行在多核系统上。但是这个模型存在一个缺点:创建一个用户线程就要创建一个相应的内核线程。由于创建内核线程的开销会影响操作系统的性能,所以这种模型的大多数实现限制了系统支持的线程数量,Linux、Window家族都实现了一对一模型。 多对多模型多路复用多个用户级线程到同样数量或更少数量的内核线程。内核线程的数量可能与特定应用程序或特定机器有关(应用程序在多处理器上比在单处理器上可能分配到更多数量的线程)。 多对多模型的一种变种仍然是多路复用多个用户级线程到同样数量或更少数量的内核线程,但是也允许绑定某个用户线程到一个内核线程上。这种变种成为双层模型(two-level-model)。比如在Solaris系统第九版之前就支持这种双层模型。 多对多模型没有上面两个模型的缺点,开发人员可以创建任意多的用户线程,并且相应的内核线程能在多处理器上来并发的执行,而且,当一个线程执行堵塞系统调用时,内核可以调度另外一个线程来执行。 在上面的模型介绍中,我们提到了通过线程库来创建、管理线程,那么什么是线程库呢?线程库(Thread library)是为开发人员提供创建和管理线程的一套API. 目前有三种主要的线程库:POSIX Pthread、Window API、Java Pthread作为POSIX标准的扩展,可以提供用户级或内核级的库。 当一个多线程程序开始执行的时候,它有一个线程在跑,就是执行main()*函数的线程。这已经是一个完整的线程,有它自己的*thread ID。创建一个新的线程,应该调用pthread_create()函数。下面给出了使用它的例子: 关于该程序需要知道的几点: 为了使用编译多线程程序gcc,我们需要将它与pthreads库链接。假设系统上已经安装了这个库(pthread),下面是如何编译我们的第一个程序: 运行多个使用相同内存空间的线程时的一个基本问题是确保它们不会“踩到彼此的脚趾”。通过这个我们指的是使用来自两个不同线程的数据结构的问题。 例如,考虑两个线程尝试更新两个变量的情况。一个尝试将两者都设置为0,另一个尝试将两者都设置为1.如果两个线程同时尝试这样做,我们可能会遇到一个变量包含1,一个包含0的情况。这是因为上下文切换(我们已经知道现在是什么,对吧?)可能会在第一个步骤清零第一个变量后发生,然后第二个线程会将两个变量都设置为1,当第一个线程恢复运行时,它将第二个变量归零,从而将第一个变量设置为“1”,将第二个变量设置为“0”。 由pthreads库提供的解决此问题的基本机制称为互斥锁。互斥锁是一种保证三件事的锁: 从这三点我们可以看到如何使用互斥锁来确保对变量的独占访问(或者在一般的关键代码段中)。下面是一些伪代码,用于更新我们讨论的两个变量,并且可以由第一个线程使用: 同时,第二个线程将执行以下操作: 假设两个线程使用相同的互斥锁,我们可以确保在它们都运行此代码后,两个变量都设置为“0”,或者两者都设置为“1”。你需要注意这需要程序员的一些工作 - 如果第三个线程是通过一些不使用这个互斥锁的代码访问这些变量,它仍然可能搞乱变量的内容。因此,在一小组函数中包含访问这些变量的所有代码非常重要,并且始终只使用这些函数来访问这些变量。 需要声明一个类型的变量 pthread_mutex_t,然后对其进行初始化。最简单的方法是将它分配给PTHREAD_MUTEX_INITIALIZER常数。 这种类型的初始化会创建一个名为“fast mutex”的互斥锁。这意味着如果一个线程锁定了互斥锁,然后再次尝试将其锁定,它将被卡住 - 它将处于死锁状态。 还有另一种类型的互斥锁,称为“递归互斥锁”,它允许锁定它的线程多次锁定它,而不会被阻塞(但是其他试图锁定互斥锁的线程现在将被阻塞)。如果线程然后解锁互斥锁,它仍将被锁定,直到它被解锁的次数与锁定时相同。这与现代门锁的工作方式类似 - 如果顺时针旋转两次锁定它,则需要逆时针旋转两次以解锁它。可以通过将常量赋值给: 为了锁定互斥锁,我们可以使用该功能 pthread_mutex_lock()。此函数尝试锁定互斥锁,或者如果互斥锁已被另一个线程锁定,则阻止该线程。在这种情况下,当第一个进程解锁互斥锁时,该函数将返回,并且我们的进程锁定了互斥锁。以下是如何锁定互斥锁(假设它已在之前初始化): 在线程执行了必要的操作(更改变量或数据结构,处理文件或其他任何操作)后,它应该使用该pthread_mutex_unlock()函数释放互斥锁,如下所示: 在我们使用互斥锁后,我们应该销毁它。完成使用意味着没有线程需要它。如果只有一个线程完成了互斥锁,它应该保持活动状态,对于可能仍然需要使用它的其他线程。一旦完成使用它,最后一个可以使用以下pthread_mutex_destroy()功能销毁它 : 在此调用之后,此变量(a_mutex)可能不再用作互斥锁,除非它再次初始化。因此,如果太早破坏互斥锁,而另一个线程试图锁定或解锁它,该线程将从EINVAL锁定或解锁函数获取错误代码。 我写了一个例子: OS之进程管理---多线程模型和线程库(POSIX PTread) 标签:路径 load 名称 更新 als 机器 获得 初始 最简 原文地址:https://www.cnblogs.com/wangdac/p/13189597.html
多线程简介
传统的的单线程模式是每一个进程只能单个控制线程,但是随着计算机硬件的提升和多(多处理器)的普及,传统的单线程模式已经不适用于现在,所以希望一个进程能够具有多个控制线程,这样就可以同时执行多个任务了。多线程模型
多对一模型
一对一模型
多对多模型
线程库
实现线程库有两种方法:
Window线程库是用于Window操作系统的内核级线程库。
Java线程API通常采用宿主系统的线程库来实现,也就是说在Win系统上,Java线程API通常采用Win API来实现,在UNIX类系统上,采用Pthread来实现。创建和销毁线程
#include
gcc pthread_create.c -o pthread_create -lpthread
使用互斥锁同步线程
什么是互斥体?
锁定互斥锁‘X1‘。
将第一个变量设置为“0”。
将第二个变量设置为“0”。
解锁互斥锁‘X1‘。
锁定互斥锁‘X1‘。
将第一个变量设置为“1”。
将第二个变量设置为“1”。
解锁互斥锁‘X1‘。
创建和初始化互斥锁
pthread_mutex_t a_mutex = PTHREAD_MUTEX_INITIALIZER;
PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP 互斥变量来创建这种互斥锁。锁定和解锁互斥锁
int rc = pthread_mutex_lock(&a_mutex);
if (rc) { /* an error has occurred */
perror("pthread_mutex_lock");
pthread_exit(NULL);
}
/* mutex is now locked - do your stuff. */
rc = pthread_mutex_unlock(&a_mutex);
if (rc) {
perror("pthread_mutex_unlock");
pthread_exit(NULL);
}
rc = pthread_mutex_destroy(&a_mutex);
#include
参考:
文章标题:OS之进程管理---多线程模型和线程库(POSIX PTread)
文章链接:http://soscw.com/index.php/essay/83172.html