Linux学习06——线程控制与同步互斥

概述

学习目标:

  • 理解线程概念和并发特征,分辨线程与进程的区别与联系
  • 掌握多线程应用编程技术,掌握线程间数据传递基本方法
  • 掌握共享变量识别方法,理解多线程访问共享变量可能带来的问题
  • 理解临界资源、临界区、线程互斥、线程同步基本概念
  • 理解保证临界区互斥执行的基本思想
  • 掌握用信号量和P/V操作来解决互斥、同步问题的编程方法
  • 掌握生产者/消费者、读者/写者问题两个经典同步问题的编程方法,并用以分析和解决实际应用
  • 了解AND型信号量、信号量集、条件变量和管程等同步机制
  • 理解线程安全、可重入型、线程竞争基本概念
  • 掌握利用多线程并发编程基本方法
  • 掌握并发程序性能分析基本方法

6.1 线程概念

6.1.1 什么是线程

传统应用程序特点与不足

启动一个传统C语言程序,产生一个进程,进程从main()函数开始,沿着程序流程往下执行,不严格地说,可认为每次仅执行一条语句(或一条指令),前一条语句(或指令)完成,后一条语句(或指令)才能开始。不足之处:

  • 一个进程只有一个代码执行序列(或控制流),只能接受一个CPU(或CPU核)为其服务,不便发挥多CPU或多核系统强大的计算能力
  • 进程每段时间只能执行一项活动,若有多项需要并发执行的活动,传统程序结构很难进行有效协调。比如程序在等待用户输入的同时,还要从消息队列接收消息,而此时用户输入尚未完成,消息还未到来。很难同时协调和管理多项并发活动,尤其是需要等待某种事件发生的活动。

什么是线程

采用多线程机制可以很好地解决前述问题。

  • 什么是线程:线程定义为进程内一个执行单元或一个可调度实体,每个执行单元可执行进程的一段程序代码(如函数)。在一个进程内可创建多个线程,这些线程都是并发逻辑流,每个线程可执行一项独立的活动或功能。 如Web服务器一个线程在给某浏览器产生网页时,另一线程就可侦听其他浏览器请求
  • 线程共享进程资源:属于同一进程的多个线程位于同一个地址空间内,共享进程拥有的资源,包括代码、数据(全局变量)、堆和打开文件等,线程需栈、程序计数器等少量资源,线程又称轻量级进程(LWP)

线程结构和状态

  •  线程结构:每个线程拥有一个线程控制块TCB(Thread Control Block)和一个线程栈,TCB用于存放线程相关属性,栈用于给函数调用、局部变量分配内存
  • TCB内容:与线程相关的属性放在线程控制块(TCB)内,TCB包括线程ID(Thread TID)、线程状态、栈指针、通用寄存器、程序计数器和标志寄存器
  • 线程比进程开销小:因线程工作所需的大部分资源和属性在进程中,线程需维护的资源、属性很少,线程创建、销毁所需开销很低(甚至低于进程开销的10%)
  • 线程基本状态及其转换

6.1.2 线程执行模型

  • 线程创建:进程启动时,先执行main函数,这个执行体为主线程(main thread);主线程在某个时刻可创建新的线程,称为对等线程(peer thread);此后各线程也可以根据需要创建更多对等线程
  • 线程间关系:线程之间无父子关系,都是对等的,一个进程相关的线程组成一个对等线程池(pool),独立于其他进程创建的线程
  • 好处:一个线程可以终止任何其他对等线程,或者等待任意其他对等线程终止
  • 线程间并发关系:各线程可因sleep、read等慢速系统调用,走走停停,交错往前推进

6.1.3 多线程应用

  • 让程序同时做多件事情。示例:在编辑文档的同时对文档中的单词个数进行实时统计。
  • 将一个耗时的进程任务划分成很多小任务,同时在多个CPU或核上执行。如大矩阵运算、海量数据检索
  • 管理多项并发活动。
  1. 示例1:对一个混杂输入、计算和输出的应用程序,输入、计算、输出各安排一个线程来做
  2. 示例2:通过多线程让进程同时等待多个事件,如网络连接、消息
  3. 示例3:网络服务器同时处理多个客户连接

6.1.4 第一个线程

  • pthread创建一个对等线程,对等线程的任务是peertask
  • 之后主线程与对等线程一起往下执行,由于每个线程执行输出一行文本后都usleep,让出CPU,控制两个线程来回切换
  • 对等线程peertask的return语句终止之后,主线程调用pthread_join函数等待对等线程终止,最后调用exit(0)终止整个程序

6.2 多线程并发特性与编程方法

6.2.1 Pthreads线程API

Pthreads提供了phtread_create、pthread_exit、pthread_join、pthread_detach、pthread_cancel等API函数,用于创建、退出、回收、分离和取消线程。

1. 创建线程

  • 创建线程

typedef void *(*Func) (void *arg);

int pthread_create(pthread_t *tid, pthread_attr_t *attr, Func fun,void *arg);

  • 获得线程TID: pthread_t pthread_self(void);

2. 终止线程

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值