目录
一、基本知识点
- 线程定义
线程(Thread)是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。每一个进程都至少包含一个main线程。
相比于进程而言,线程更加轻量级,因为它们共享了进程的地址空间以及其他资源,所以线程之间的切换和通信会更加高效。一个进程可以包含多个线程,这些线程可以并发执行,各自独立完成一些特定的任务,或者共同完成一个复杂的任务。进程里每个线程执行的顺序不一定。主线程结束,则所有线程结束。
- CPU核心和线程的关系
线程也为任务,当CPU为多核心时则可以多个任务并发进行。一般一个核心对应了一个线程,而intel开发出了
超线程技术
,1个核心能够做到2个线程计算,而6个核心则能够做到12个线程,超线程技术的好处就是无需增加物理核心就可以明显的进步CPU多线程功能,毕竟增加物理核心是需要占据非常大的核心面积,成本也随之增加。
一般来说(除超线程技术),单核CPU最多同时只有一个任务进行。双核CPU最多两个任务(线程)同时进行。说白点就是核心数和线程数量越多,越适合多开软件或者游戏,打开的任务越多,除了多开程序,还有渲染需求,核数和线程数越多,越有利。
- 共享资源保护
由于子线程与同属一个进程的其他的线程共享进程的资源,如内存空间、文件描述符和其他一些进程相关的属性。所以在多线程编程中,通常会涉及到共享资源保护操作,如互斥锁等以确保线程之间的协调运行,避免资源竞争和数据不一致的问题。即每次对共享资源进行操作时,只能有一个线程操作,其他线程必须等待操作完毕后,才能对其继续操作。
二、线程的编译
Linux 的线程是通过用户级的函数库实现的,一般采用
pthread
线程库实现线程的访问和控制。它用第 3 方 posix 标准的 pthread,具有良好的可移植性。在使用了线程的代码编译的时候要在后面加上-lpthread
。
例如:gcc test.c -o test -lpthread
三、 线程相关函数
头文件:
#include <pthread.h>
特别注意:这线程的这三个函数是共同使用的,只要使用了创建线程,那么就必须有线程的退出和等待函数,以确保线程被正确的释放资源,从而确保程序执行的正确性。
1. 线程的创建
int pthread_create(pthread_t* thread, pthread_attr_t * attr, void *(*start_routine)(void *), void * arg);
//pthread_t* thread :线程的句柄,用于区分是哪个线程。
//pthread_attr_t * attr :线程的属性,通常为NULL。
//void *(*start_routine)(void *) :线程所执行的函数,该函数形参和返回值都要为void *。
// void * arg :该值用于传递第三个参数函数的形参,如果不传递可以为NULL。
举例:
(1)整型的传入与接收
#include <sys/types.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
void *task(void *arg)
{
int num= *(int *)arg;
while(1)
{
sleep(1);
printf("我是子线程,传入参数为%d\n", num);
}
}
int main()
{
int num =100;
pthread_t thread; //定义线程句柄
pthread_create(&thread, NULL, task, (void *)&num); //创建线程,并绑定线程函数。
while(1){
sleep(1);
printf("我是主线程\n");
}
}
(2)浮点数的传入与接收
#include <sys/types.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
void *task(void *arg)
{
float num=*(float *)arg;
while(1)
{
sleep(1);
printf("我是子线程,传入参数为%f\n", num);
}
}
int main()
{
float num =10.10;
pthread_t thread; //定义线程句柄
pthread_create(&thread, NULL, task, (void *)&num); //创建线程,并绑定线程函数。
while(1){
sleep(1);
printf("我是主线程\n");
}
}
(3)字符串的传入与接收
#include <sys/types.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
void *task(void *arg)
{
char *num=(char *)arg;
while(1)
{
sleep(1);
printf("我是子线程,传入参数为%s\n", num);
}
}
int main()
{