《多核与GPU编程:工具、方法及实践》----第3章 共享内存编程:线程 3.1 引言

简介: 本章目标: 学习线程的定义以及创建方法。 学习完成特定任务的初始化线程方法。 学习多种终止多线程程序的技术。 理解多线程访问共享数据过程中的主要问题,例如竞争和死锁。

本节书摘来自华章出版社《多核与GPU编程:工具、方法及实践》一书中的第3章,第3.1节, 作 者 Multicore and GPU Programming: An Integrated Approach[阿联酋]杰拉西莫斯·巴拉斯(Gerassimos Barlas) 著,张云泉 贾海鹏 李士刚 袁良 等译, 更多章节内容可以访问云栖社区“华章计算机”公众号查看。

第3章

共享内存编程:线程

本章目标:

学习线程的定义以及创建方法。

学习完成特定任务的初始化线程方法。

学习多种终止多线程程序的技术。

理解多线程访问共享数据过程中的主要问题,例如竞争和死锁。

学习信号量和监视器的定义和使用方法。

熟悉经典同步问题及其解决方法。

学习运行时动态管理线程。

学习多线程程序的调试技术。

3.1 引言

从20世纪60年代麻省理工学院引入兼容分时系统(CTSS)以来,多个程序并发执行的现象已经变得较为常见。操作系统通过中断当前正在执行的程序并将CPU的控制权交由另一个程序来完成这一功能。这种能有效地在多个程序间共享CPU时间(也即分时)的切换可以通过以下条件触发:

时钟或定时器的定期硬件中断

不定期硬件中断,例如某些设备的请求

调用操作系统功能,例如执行输入/输出(I/O)操作

每个运行中的程序组成一个进程,亦即为了管理程序,一个包括代码、数据、资源和执行状态信息的操作系统实体。

因此,每个进程值能在一个“时间片”内获得CPU的控制权,然后将控制权交回操作系统,操作系统再将CPU交于另一个进程,以此类推。单CPU上的分时如图3-1a所示。

分时这种方式可以提高计算资源的使用效率,但是它不能提高单个进程的运行速度,并且分时可能会由于减少分配给某个进程的时间片而直接降低程序性能,或者由于频繁调用操作系统的任务调度程序的开销而间接降低程序性能。

为了使程序获得更多的计算时间(利用调度制导语句改变程序优先级),必须将其划分为多个进程,在多核系统上也必须采取同样的方法才能提高性能,此类示例如图3-1b所示。最原始的生成(creating或者spawning)方法是调用fork函数,代码清单3-1给出了一个示例。


0ba958950257941fc4c961d90bb4a58b66bf120a


e6487ef3eb8e4b7816f97801dc9ec3e95aaf2c74

生成一个进程需要精确复制当前进程的内存,包括所有代码和数据,如图3-2所示。在原始程序(父进程)和生成程序(子进程)间的唯一区别是子进程继续执行fork语句的后的部分,亦即子进程没有收到返回值,因此子进程中的ChildID为0(见代码清单3-1第13行)。逻辑上看,就像一个新的进程开始在此处执行,从而使得两个进程执行不同任务(使两个进程执行同样的任务是无意义的)。

这种进程生成机制中一些显而易见的问题包括:

为什么复制代码?它不应该在内存不可变区吗?

子进程有父进程的所有数据的副本,那么如何在两个进程间交换信息?

由于有些程序在运行时改变代码,因此需要复制代码。这也是病毒中的常见特征,但这并不是一个正常的程序行为。对于后一个问题,系统已经提供了多种解决该问题 的机制,但是最为简单的还是访问一组共享变量。


4874395d58b7e2f137fe475365db7073da16acae

由于fork函数中保留和复制程序映像的开销,因此这种方法较为低效。幸运的是,还存在另一种通过线程来实现并发的方法,这将在下面进行介绍。

相关实践学习
基于阿里云DeepGPU实例,用AI画唯美国风少女
本实验基于阿里云DeepGPU实例,使用aiacctorch加速stable-diffusion-webui,用AI画唯美国风少女,可提升性能至高至原性能的2.6倍。
相关文章
|
4天前
|
Java 程序员 开发者
深入理解Java并发编程:线程同步与锁机制
【4月更文挑战第30天】 在多线程的世界中,确保数据的一致性和线程间的有效通信是至关重要的。本文将深入探讨Java并发编程中的核心概念——线程同步与锁机制。我们将从基本的synchronized关键字开始,逐步过渡到更复杂的ReentrantLock类,并探讨它们如何帮助我们在多线程环境中保持数据完整性和避免常见的并发问题。文章还将通过示例代码,展示这些同步工具在实际开发中的应用,帮助读者构建对Java并发编程深层次的理解。
|
4天前
|
Java
Java并发编程:深入理解线程池
【4月更文挑战第30天】本文将深入探讨Java并发编程中的一个重要主题——线程池。我们将从线程池的基本概念入手,了解其工作原理和优势,然后详细介绍如何使用Java的Executor框架创建和管理线程池。最后,我们将讨论一些高级主题,如自定义线程工厂和拒绝策略。通过本文的学习,你将能够更好地理解和使用Java的线程池,提高你的并发编程能力。
|
4天前
|
安全 Java 调度
深入理解Java并发编程:线程安全与性能优化
【4月更文挑战第30天】本文将深入探讨Java并发编程的核心概念,包括线程安全、同步机制、锁优化以及性能调优。我们将通过实例分析如何确保多线程环境下的数据一致性,同时介绍一些常见的并发模式和最佳实践,旨在帮助开发者在保证线程安全的同时,提升系统的性能和响应能力。
|
3天前
|
存储 安全 Java
深入理解Java并发编程:线程安全与性能优化
【5月更文挑战第1天】本文将深入探讨Java并发编程的核心概念,包括线程安全和性能优化。我们将详细分析线程安全问题的根源,以及如何通过合理的设计和编码实践来避免常见的并发问题。同时,我们还将探讨如何在保证线程安全的前提下,提高程序的并发性能,包括使用高效的同步机制、减少锁的竞争以及利用现代硬件的并行能力等技术手段。
|
3天前
|
缓存 Java 调度
Java并发编程:深入理解线程池
【4月更文挑战第30天】 在Java并发编程中,线程池是一种重要的工具,它可以帮助我们有效地管理线程,提高系统性能。本文将深入探讨Java线程池的工作原理,如何使用它,以及如何根据实际需求选择合适的线程池策略。
|
3天前
|
Java
Java并发编程:深入理解线程池
【4月更文挑战第30天】 本文将深入探讨Java中的线程池,解析其原理、使用场景以及如何合理地利用线程池提高程序性能。我们将从线程池的基本概念出发,介绍其内部工作机制,然后通过实例演示如何创建和使用线程池。最后,我们将讨论线程池的优缺点以及在实际应用中需要注意的问题。
|
4天前
|
存储 安全 Java
深入理解Java并发编程:线程安全与性能优化
【4月更文挑战第30天】在Java开发中,并发编程是一个复杂而又关键的领域。它允许多个线程同时执行,从而提高程序性能和资源利用率。然而,并发编程也带来了许多挑战,如数据不一致、死锁和线程安全问题。本文将深入探讨Java并发编程的核心概念,包括线程安全和性能优化策略。我们将通过实例分析如何在保证线程安全的同时提高程序性能,为Java开发者提供实用的指导。
|
4天前
|
Java
Java并发编程:深入理解线程池
【4月更文挑战第29天】在Java中,线程池是一种管理线程的强大工具,它可以提高系统性能,减少资源消耗。本文将深入探讨Java线程池的工作原理,如何使用它,以及在使用线程池时需要注意的问题。
|
4天前
|
安全 Java
深入理解Java并发编程:线程安全与性能优化
【4月更文挑战第29天】本文将深入探讨Java并发编程的核心概念,包括线程安全和性能优化。我们将首先介绍线程安全的基本概念,然后讨论如何在Java中实现线程安全,包括使用synchronized关键字和Lock接口。接下来,我们将探讨Java并发编程的性能优化策略,如减少锁的粒度、使用读写锁和无锁数据结构。最后,我们将通过实例演示如何在实际项目中应用这些技术。
|
4天前
|
Java
Java并发编程:深入理解线程池
【4月更文挑战第29天】 在Java并发编程中,线程池是一种重要的工具,它可以帮助我们管理线程资源,提高系统性能。本文将深入探讨线程池的工作原理、使用方法以及如何根据实际需求选择合适的线程池参数。通过阅读本文,你将能够更好地理解和使用Java线程池,提高你的并发编程能力。