多线程编程(C语言版)

本文详细介绍了Linux中使用C语言进行多线程编程的相关知识,包括线程的概念、创建与管理、同步互斥。通过示例代码演示了线程的创建、退出、资源回收、线程私有数据、线程属性设置、互斥锁、读写锁以及条件变量的使用,以解决多线程中的并发问题。
摘要由CSDN通过智能技术生成

本文探讨PODIX线程相关内容

线程的概念

什么是多线程,提出这个问题的时候,我还是很老实的拿出操作系统的书,按着上面的话敲下“为了减少进程切换和创建开销,提高执行效率和节省资源,我们引入了线程的概念,与进程相比较,线程是CPU调度的一个基本单位。”

当 Linux 最初开发时,在内核中并不能真正支持线程。那为什么要使用多线程?

使用多线程的理由之一是和进程相比,它是一种非常"节俭"的多任务操作方式。运行于一个进程中的多个线程,它们彼此之间使用相同的地址空间,共享大部分数据,启动一个线程所花费的空间远远小于启动一个进程所花费的空间,而且,线程间彼此切换所需的时间也远远小于进程间切换所需要的时间。

那么线程是干什么的呢?简要概括下线程的职责:线程是程序中完成一个独立任务的完整执行序列。

线程的管理

创建线程

#include <pthread.h>
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
    void *(*start_routine) (void *), void *arg);

- thread:线程id,唯一标识

- attr:线程属性,参数可选

- start_routine:线程执行函数

- arg:传递给线程的参数

Demo1:创建一个线程

#include <pthread.h>
#include <stdio.h>

void *workThreadEntry(void *args)
{
 char*str = (char*)args;
    printf("threadId:%lu,argv:%s\n",pthread_self(),str);
}
int main(int argc,char *agrv[])
{
 pthread_t thread_id;
    char*str = "hello world";
 pthread_create(&thread_id,NULL,workThreadEntry,str);
 printf("threadId=%lu\n",pthread_self());
 pthread_join(thread_id,NULL);
}

编译运行

$ gcc -o main main.c -pthread
$ ./main 
threadId=140381594486592
threadId:140381585938176,argv:hello world

运行结果是创建一个线程,打印线程id和主线程传递过来的参数。

线程退出与等待

在Demo1中我们用到了pthread_join这个函数

#include <pthread.h>
int pthread_join(pthread_t thread, void **retval);

这是一个阻塞函数,用于等待线程退出,对线程资源进行收回。

一个线程对应一个pthread_join()调用,对同一个线程进行多次pthread_join()调用属于逻辑错误,俗称耍流氓。

那么线程什么时候退出?

1.在线程函数运行完后,该线程也就退出了

2.线程内调用函数pthread_exit()主动退出

3.当线程可以被取消时,通过其他线程调用pthread_cancel的时候退出

4.创建线程的进程退出

5.主线程执行了exec类函数,该进程的所有的地址空间完全被新程序替换,子线程退出

线程的状态

线程pthread有两种状态joinable状态和unjoinable状态,如果线程是joinable状态,当线程函数自己返回退出时或pthread_exit时都不会释放线程所占用堆栈和线程描述符(总计8K多)。只有当你调用了pthread_join之后这些资源才会被释放。若是unjoinable状态的线程,这些资源在线程函数退出时或pthread_exit时自动会被释放。pthread的状态在创建线程的时候指定,创建一个线程默认的状态是joinable

状态为joinable的线程可在创建后,用pthread_detach()显式地分离,但分离后不可以再合并,该操作不可逆。

#include <pthread.h>
int pthread_detach(pthread_t thread);

pthread_detach这个函数就是用来分离主线程和子线程,这样做的好处就是当子线程退出时系统会自动释放线程资源。

主线程与子线程分离,子线程结束后,资源自动回收。

线程取消

在线程的退出中我们说到线程可以被其他线程结束。

1.一个线程可以调用pthread_cancel来取消另一个线程。

2.被取消的线程需要被join来释放资源。

3.被取消的线程的返回值为PTHREAD_CANCELED

有关线程的取消,一个线程可以为如下三个状态:

1.可异步取消:一个线程可以在任何时刻被取消。

2.可同步取消:取消的请求被放在队列中,直到线程到达某个点,才被取消。

3.不可取消:取消的请求被忽略。

首先线程默认是可以取消的,通过pthread_setcancelstate设置线程的取消状态属性

#include <pthread.h>
int pthread_setcancelstate(int state, int *oldstate);
int pthread_setcanceltype(int type, int *oldtype);


可取消 不可取消
PTHREAD_CANCEL_ENABLE PTHREAD_CANCEL_DISABLE

调用pthread_setcanceltype来设定线程取消的方式:

pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, NULL); //异步取消、 
pthread_setcanceltype (PTHREAD_CANCEL_DEFERRED, NULL);  //同步取消、
pthread_setcanceltype (PTHREAD_CANCEL_DISABLE, NULL); //不能取消

线程回收

Linux提供回收器(cleanup handler),它是一个API函数,在线程退出的时候被调用。

#include <pthread.h>
void pthread_cleanup_push(void (*routine)(void *),
void pthread_cleanup_
  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值