本章目标

  • 明确线程的基本组成,以及与进程之间对比
  • 描述设计多线程的好处和挑战
  • 隐式多线程的多种方式:线程池、fork-join、Grand Central Dispatch
  • 描述windows和linux操作系统如何使用线程
  • 使用Pthreads、Java和Windows的线程API设计多线程应用

Abbr.

GCD: Grand Central Dispatch

TBB: Thread Building Blocks

TLS: Thread-Local Storage

LWP: LightWeight Process

4.1 Overview

  • 线程是CPU调度的基本单元
  • 组成
    • 线程ID
    • PC(Program Counter)
    • 寄存器组
  • 同个进程下的线程共享
    • 代码段
    • 数据段
    • 其余OS资源,比如打开的文件和信号等
  • 好处
    • 响应度:一个线程宕机了别的线程可以继续执行
    • 资源共享:进程只能通过共享内存和信息传递共享资源,但线程默认是共享同个进程下的内存和资源的
    • 性价比高:创建线程分配内存和资源、切换上下文所需的消耗比进程少得多
    • 可拓展性scalability:多核架构下方便并行化

下图例子:客户端每发送一个请求,服务器就创建一个新的线程

4.2 多核编程

  • 多核编程的挑战

    • ·辨别可以分离、并发的任务
    • 平衡:并行化所带来的收益是否值得
    • 数据划分:如何将数据分配到不同的task里
    • 数据依赖:多个task之间的数据若有依赖性需要做好同步(chap 6)等操作
    • 测试和debug更具挑战性

Amdahl’s Law: 当我们对系统的某个部分加速时,其对系统整体性能的影响取决于该部分的重要性和加速程度

  • 并行化种类

    • 数据并行:每个task处理的数据是分隔开的
    • 任务并行:数据不分割,多个task可能处理同一数据

4.3 多线程模型

  • 线程类别

    • 用户线程
    • 内核线程:直接由OS支持和管理
  • 多线程模型
    • 多对一

      • 由用户管理,高效
      • 本质上还是只有一个kernel,并发性弱
      • 一个线程block就会导致整个进程block
      • 例子:Solaris Green Threads;GNU Portable Threads
    • 一对一

      • 用户开启的线程数量受到kernel资源的限制
      • 例子:Windows NT/XP/2000、Linux、Solaris 9 and later
    • 多对多

      • 灵活但实现困难
    • Two-level

      • 多对多,同时也允许一个用户线程绑定一个内核线程

4.4 线程库

线程库在用户曾难免提供创建和管理线程的API。

两种实现方式:库完全在用户层面;内核层面的库由OS直接支持。

以下代码段的例子为求和计算。

POSIX Pthreads

  • 提供用户层面和内核层面库。
  • A POSIX standard (IEEE 1003.1c) API for thread creation and synchronization
#include <pthread.h>
#include <stdio.h>int sum;    // 线程间共享的数据
void *runner(void *param);  // 线程int main(int argc, char *argv[]){pthread_t tid;pthread_attr_t attr;if(argc != 2){fprintf(stderr, "usage: a.out <integer value>\n");return -1;}if(atoi(atgv[1]) > 0){fprintf(stderr, "%d must be >= 0\n", atoi(argv[1]));return -1;}pthread_attr_init(&attr);   // 获取默认属性pthread_create(&tid, &attr, runner, argv[1]);   // 创建线程,产生对应idpthread_join(tid, NULL);    // 主程序main等待线程结束后继续printf("sum = %d\n", sum);
}void *runner(void *param){int i, upper = atoi(param);sum = 0;for(i = 1; i <= upper; i ++)sum += i;pthread_exit(0);
}

Win32

内核层面库。

#include <windows.h>
#include <stdio.h>DWORD Sum;  // 线程间共享的数据DWORD WINAPI Summation(LPVOID Param){DWORD Upper = *(DWORD*)Param;for(DWORD i = 0; i <= Upper; i ++)Sum += i;return 0;
}int main(int argc, char *argv[]){DWORD ThreadId;HANDLE ThreadHandle;int Param;// 略一些参数检查// 创建线程ThreadHandle = CreateThread(NULL,   // 默认的安全属性0,      // 默认的栈的sizeSummation,  // 线程所要执行的函数&Param,     // 函数所需的参数0,          // 默认的创建flag&ThreadId   // 返回线程id);if(ThreadHandle != NULL){// 等待线程执行结束WaitForSingleObject(ThreadHandle, INFINITE);// 关闭线程句柄CloseHandle(ThreadHandle);printf("sum = %d\n", Sum);}
}

Java

直接通过Java程序创建和管理线程。可以

1. 创建一个新的class,继承Thread class并重写run 方法

2. 定义一个实现runnable interfave的class

4.5 隐式多线程

为了更高效更可靠地创建和管理线程,现在逐步将这些任务从开发者身上转移到编译器和run-time库,这种策略就叫做隐式多线程(Implicit Threading)。

线程池

创建一定数量的线程放到pool里待命,有request就在pool里找空闲的线程执行。线程执行完后会再次被放进pool里。如果没有空闲的线程,task会被放到一个队列里等待被执行。

Fork Join

在chap 3中系统调用fork表示创建一个新的进程,在多线程程序下,fork和exec的语义有所不同。

一个线程fork,有两种情形,如果fork之后立即执行exec,则只复制该线程,否则,会复制线程所在进程下的所有线程。

OpenMP

Open Multi-Processing

参考:(46条消息) 并行编程OpenMP基础及简单示例_-牧野-的博客-CSDN博客_openmp

OpenMP是一种用于共享内存并行系统的多线程程序设计方案,支持的编程语言包括C、C++和Fortran。OpenMP提供了对并行算法的高层抽象描述,特别适合在多核CPU机器上的并行程序设计。编译器根据程序中添加的pragma指令,自动将程序并行处理,使用OpenMP降低了并行编程的难度和复杂度。当编译器不支持OpenMP时,程序会退化成普通(串行)程序。程序中已有的OpenMP指令不会影响程序的正常编译运行。

例如,运行以下代码,系统有几个core就会产生几个线程,输出几次。

#pragma omp parallel
{
printf("I am a parallel region.");
}

Grand Central Dispatch

由Apple开发,通过将任务放置到派遣队列dispatch queue里来进行运行时调度。略。

Intel TBB

由C++编写的设计并行程序的模板库,不需要特殊的编译器或语言。不必关注线程,专注任务本身;抽象层仅需很少的接口代码;多平台适用

4.6 线程问题

  • fork 和 exec的语义问题:见前文
  • 信号处理
    • 信号用来通知一个进程某个特定的事件发起了
    • 方式
      • 发送给指定线程/所有线程
      • 可以指定一个线程来接受进程监听的所有信号
  • 线程取消
    • 在线程结束前终止
    • 方式
      • 异步取消操作立即取消目标线程 pthread cancel(tid);
      • deferred 取消周期性地检查目标线程是否需要取消 pthread testcancel();
  • 线程局部存储thread-local storage (or TLS)
    • 线程特有的数据
  • 调度激活
    • 定义:用户线程库和内核之间的通信
    • 多对多和TwoLevel模型都需要通信,以维护分配给应用程序的适当数量的内核线程
      • 调度程序激活提供了回调upcall——从内核到线程库的通信机制; 这种通信允许应用程序维护正确的内核线程数
    • Lightweight process (LWP): 用户线程和内核线程之间的中间数据结构,每个LWP对应一个内核线程
    • CPU-bound程序使用一个线程(一个LWP)就足够;I/O-bound程序一般需要多个LWP来执行,例如打印机。

4.7 OS例子

Windows XP Threads

用户层面:

TEB(thread environment block): 线程环境块

内核层面:

Ethread:执行线程块

Kthread:内核线程块

如上图,各个块之间通过指针关联。

Linux Threads

Linux不区分进程和线程,都看作task看待。

系统调用clone用来创建新的task,创建时通过flag指定子任务和父任务共享多少资源。

Takeaways

  1. 四种多线程模型
  2. 一些常用线程库
  3. 线程和进程之间的资源关系
    1. 一个进程下的所有线程共享的数据有哪些?
    2. 哪些是线程specific的数据?

<OS Concepts 9th> Chap 4 线程与并发相关推荐

  1. [Operating.System.Concepts(9th,2012.12)].Abraham.Silberschatz.文字版(恐龙书——操作系统概念 原书第九版)课后习题 参考答案

    目录 Chap01 导论 Chap02 OS结构 Chap03 进程 Chap04 线程 Chap05 同步(Synchronization) Chap06 CPU调度 Chap07 死锁 Chap0 ...

  2. CPU核心数线程数、程序进程线程、并发并行的简单理解

    CPU核心数线程数.程序进程线程.并发并行.简单理解和区分 这篇文章是对上述感念的简单理解,想深入研究可以看看<计算机组成原理> CPU的核心数 线程数 当我们买电脑的时候,会看到CPU的 ...

  3. 多少并发量算高并发_如何理解:程序、进程、线程、并发、并行、高并发?

    作者:大宽宽 链接:http://tinyurl.com/wx5xxho 在这里你可以了解: 为啥大家说的进程的意思有出入? 为啥并发那么难理解? 为啥高并发不仅仅是"高"+&qu ...

  4. 【Java扫盲篇】今天用人话给你讲清楚:进程、线程、并发、并行、高并发?

    在这里你可以了解: 为啥大家说的进程的意思有出入? 为啥并发那么难理解? 为啥高并发不仅仅是 "高"+"并发" 的意思? 为啥这些概念到了现实当中就不一样了? ...

  5. 如何理解:程序、进程、线程、并发、并行、高并发?

    在这里你可以了解: 为啥大家说的进程的意思有出入? 为啥并发那么难理解? 为啥高并发不仅仅是"高"+"并发"的意思? 为啥这些概念到了现实当中就不一样了? 进程 ...

  6. Ice笔记--C++线程与并发(小结)

    C++线程与并发(Ice3.4.2) 概述 Ice服务器是多线程模型的.在涉及资源的访问和操作的时候将要考虑同步访问机制. Ice线程库提供了一些与线程有关的抽象: 互斥体,递归互斥体,读写递归互斥体 ...

  7. ASP.NET MVC 线程和并发

    我也想过跳过C#高级知识点概要直接讲MVC,但经过前思后想,还是觉得有必要讲的.我希望通过自己的经验给大家一些指引,带着大家一起走上ASP.NET MVC大牛之路,少走弯路.同时也希望能和大家一起交流 ...

  8. .Net组件程序设计之线程、并发管理(二)

    .Net组件程序设计之线程.并发管理(二) 2.同步线程 手动同步 监视器 互斥 可等待事件 同步线程 所有的.NET组件都支持在多线程的环境中运行,可以被多个线程并发访问,如果没有线程同步,这样的后 ...

  9. C#线程 在某一时间内,只有N个线程在并发执行,其余都在队列中的实现(转载)...

    具体的需求是 在某一时间点,只有N个线程在并发执行,如果有多余的线程,则排队等候~ 还真是费尽心思啊~最终还是被我攻克了~ 下面我就来说说具体的实现 C#提供了Mutex与Interlocked这两个 ...

最新文章

  1. TF-IDF 原理及sklearn中的tf-idf实例分析
  2. Linux 之父归来!
  3. 第25节 典型应用集成技术
  4. 2016年印度光伏设备市场将猛增2倍达4GW以上
  5. gd-flags |= GD_FLG_RELOC; 问题遗留
  6. centos6 yum mysql_centos6_yum_mysql
  7. 在Spring Boot里面,怎么获取定义在application.properties文件里的值
  8. nginx支持php解析,upstream模块
  9. java setenabled不好用,哪个更好,setEnabled或setUserInteractionEnabled?
  10. javascript之复习(框架里的方法们)
  11. java mongo分组统计_mongodb 分组 topN
  12. 内存映射(Memory Map)
  13. C语言malloc函数详解(通俗易懂)
  14. html用css设置图片大小,css如何设置图片大小?
  15. oracle11g dataguard
  16. 图形化生物软件专题(4):MEGAN
  17. 腾讯信鸽自定义推送通知
  18. 反诈中心拦截网站域名措施与申诉方法
  19. Cell Reports:任栓成/高东/胡志安/唐玲团队合作揭示压力性失眠发生的神经机制
  20. 3D建模教学 | 卡通石头高模制作技巧

热门文章

  1. Python中Django与Echarts的结合用法
  2. 第一百篇,真实可重现,详细实现昨日剩下的功能
  3. ios 单元测试覆盖率怎么查看_iOS 覆盖率检测原理与增量代码测试覆盖率工具实现...
  4. 用python-sklearn做广州房价预测——以此为例说明如何使用python做简单的数据分析
  5. 如何从 SQL Server 中的 SELECT 更新?
  6. 论文笔记:Eye In-Painting with Exemplar Generative Adversarial Networks
  7. win10应用商店打不开,错误代码0x80131500
  8. 达梦安装报错 could not load SWT library. Reasons:no swt…....No such file or directory
  9. 链家网页爬虫_分享最近做的一个链家二手房爬虫和对爬到的数据进行可视化分析的案例...
  10. css网页制作的基本步骤,以图例方式介绍CSS制作网页详细步骤