Linux多线程编程

本文详细介绍了Linux下的线程编程,包括线程与进程的区别,线程的创建、等待、分离和退出,以及线程取消和清理处理程序。线程在减少系统开销、提高并发性和资源利用率方面具有优势,适用于多任务、并发程序和网络程序设计。通过pthread_create创建线程,pthread_join等待线程退出,pthread_detach实现线程分离,pthread_cancel则用于线程取消。
摘要由CSDN通过智能技术生成

线程概述:
每个进程都拥有自己的数据段、代码段和堆栈段,这就造成进程在进行创建、切换、撤销操作时,需要较大的系统开销。
为了减少系统开销,从进程中演化出了线程。
线程存在于进程中,共享进程的资源。
线程是进程中的独立控制流,由环境(包括寄存器组和程序计数器)和一系列的执行指令组成。
每个进程有一个地址空间和一个控制线程。
在这里插入图片描述
线程和进程的比较:
调度:
线程是CPU调度和分派的基本单位。
拥有资源:
进程是系统中程序执行和资源分配的基本单位。
线程自己一般不拥有资源(除了必不可少的程序计数器,一组寄存器和栈),但它可以去访问其所属进程的资源,如进程代码段,数据段以及系统资源(已打开的文件,I/O设备等)。
系统开销:
同一个进程中的多个线程可共享同一地址空间,因此它们之间的同步和通信的实现也变得比较容易。在进程切换时候,涉及到整个当前进程CPU环境的保存以及新被调度运行的进程的CPU环境的设置;而线程切换只需要保存和设置少量寄存器的内容,并不涉及存储器管理方面的操作,从而能更有效地使用系统资源和提高系统的吞吐量。
并发性:
不仅进程间可以并发执行,而且在一个进程中的多个线程之间也可以并发执行。
总结:
一般把线程称之为轻量级的进程;
一个进程可以创建多个线程,多个线程共享一个进程的资源;
每一个进程创建的时候系统会给其4G虚拟内存,3G用户空间是私有的,所以进程切换时,用户空间也会切换,所以会增加系统开销,而一个进程中的多个线程共享一个进程的资源,所以线程切换时不用切换这些资源,效率会更高;
线程的调度机制跟进程是一样的,多个线程来回切换运行;

多线程的用处:
使用多线程的目的主要有以下几点:
多任务程序的设计
一个程序可能要处理不同应用,要处理多种任务,如果开发不同的进程来处理,系统开销很大,数据共享,程序结构都不方便,这时可使用多线程编程方法。
并发程序设计
一个任务可能分成不同的步骤去完成,这些不同的步骤之间可能是松散耦合,可能通过线程的互斥,同步并发完成。这样可以为不同的任务步骤建立线程。
网络程序设计
为提高网络的利用效率,我们可能使用多线程,对每个连接用一个线程去处理。
数据共享
同一个进程中的不同线程共享进程的数据空间,方便不同线程间的数据共享。
在多CPU系统中,实现真正的并行。

线程的基本操作:
线程的创建:
在这里插入图片描述

1 #include <pthread.h>
2 int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
3  void *(*start_routine) (void *), void *arg);
4 功能:创建一个新的子线程
5 参数:
6  thread:当前创建的线程id
7  attr:线程的属性,设置为NULL表示以默认的属性创建
8  start_routine:线程处理函数,如果当前函数执行完毕,则子线程也执行完毕
9  arg:给线程处理函数传参用的
10 返回值:
11  成功:0
12  失败:非0

注意事项:
与fork不同的是pthread_create创建的线程不与父线程在同一点开始运行,而是从指定的函数开始运行,该函数运行完后,该线程也就退出了。
线程依赖进程存在的,如果创建线程的进程结束了,线程也就结束了。
线程函数的程序在pthread库中,故链接时要加上参数-lpthread。
案例:

#include<pthread.h>
//由于线程库原本不是系统本身的,所以在链接时需要手动链接库文件gcc *.c -lpthread
void *thread_fun(void *arg)
{
   
  printf("子线程正在运行\n");
}
int main(int argc,char const *argv[])
{
   
  printf("主控线程正在执行\n");
  pthread_t thread;
  //通过pthread_creat函数创建子线程
  if(pthread_create(&thread,NULL,thread_fun,NULL) != 0)
  {
   
    perror("fail to pthread_creat");
    exit(1);
  }
  //由于进程结束后,进程中所有的线程都会强制退出,所以现阶段不要让进程退出
  while(1);
  return 0;
}

在这里插入图片描述
案例:线程调度机制的验证

#include<stdio.h>
#include<stdlib.h>
#include<pthread.h>
#include<unistd.h>
//一个线程中的多个线程执行顺序是不确定的,没有先后顺序可言
//多线程执行时跟进程一样,是来回切换运行的,跟进程的调度机制一样
void *pthread_fun1(void *arg)
{
   
  printf("子线程1正在运行\n");
  sleep(1);
  printf("*****************\n");
}
void *pthread_fun2(void *arg)
{
   
  printf("子线程2正在运行\n");
  sleep(1);
  printf("-----------------\n");
}
int main(int argc,char const *argv[])
{
   
  pthread_t thread1,thread2;
  if(pthread_create(&thread1,NULL,pthread_fun1,NULL) != 0)
  {
   
    perror("fail to pthread_create");
  }
  if(pthread_create(&thread2,NULL,pthread_fun2,NULL) != 0)
  {
   
     perror("fail to pthread_create");
  }
  while(1);
  return 0;
}

在这里插入图片描述
案例:线程处理函数的传参

#include<stdio.h>
#include<stdlib.h>
#include<pthread.h>
#include<unistd.h>
int num=100;
//线程处理函数可以认为就是一个普通的全局函数,只不过与普通函数最大的区别在于。
//线程处理函数是并发执行,来回交替执行,但是普通函数一定是按照顺序一个一个执行
void *pthread_fun1(void *arg)
{
   
  printf("子线程1:num = %d\n",num);
  num++;
  int n = *(int *)arg;
  printf("1 n =%d\n",n);
  *(int *)arg = 111;
}
void *pthread_fun2(void *arg)
{
   
  sleep(1);
  printf("子线程2:num = %d\n",num);
  int n = *(int *)arg;
  printf("2 n = %d\n",n);
}
int main(int argc,char const *argv[])
{
   
  pthread_t threaed1,thread2;
  int a=666;
  if(pthread_create(&thread1,NULL,pthread_fun1,(void *)&a) !=0)
  {
   
    perror("fail to pthread_create");
  }
  if(pthread_create(&thread2,
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值