线程的概念
每个进程都拥有自己的数据段、代码段和堆栈段,这就造成进程在进行创建、切换、撤销操作时,需要较大的系统开销
为了减少系统开销, 从进程中演化出了线程
线程存在于进程***享进程的资源
线程是进程中的独立控制流, 由环境(包括寄存器组和程序计数器) 和一系列的执行指令组成
每个进程有一个地址空间和一个控制线程
线程和进程的比较
调度:
线程是 CPU 调度和分派的基本单位
拥有资源:
进程是系统中程序执行和资源分配的基本单位
线程自己一般不拥有资源( 除了必不可少的程序计数器, 一组寄存器和栈), 但它可以去访问其所属进程的资源, 如进程代码段, 数据段以及系统资源( 已打开的文件, I/O 设备等)
系统开销:
同一个进程中的多个线程可共享同一地址空间,因此它们之间的同步和通信的实现更容易
在进程切换时,涉及到整个当前进程 CPU 环境的保存以及新被调度运行的进程的 CPU 环境的设置; 而线程切换只需要保存和设置少量寄存器的内容,并不涉及存储器管理方面的操作,从而能更有效地使用系统资源和提高系统的吞吐量
并发性:
进程间不仅可并发执行,而且在一个进程中的多个线程之间也可以并发执行
多线程的用处
使用多线程的目的:
多任务程序的设计:
一个程序可能要处理不同应用,要处理多种任务,如果开发不同的进程来处理,系统开销很大,数据共享,程序结构都不方便, 这时可使用多线程编程方法
并发程序设计:
一个任务可能分成不同的步骤去完成,这些不同的步骤之间可能是松散耦合,可能通过线程的互斥,同步并发完成。这样可以为不同的任务步骤建立线程
网络程序设计:
为提高网络的利用效率,我们可能使用多线程,对每个连接用一个线程去处理
数据共享:
同一个进程中的不同线程共享进程的数据空间,方便不同线程间的数据共享
在多 CPU 系统中, 实现真正的并行
线程的基本操作
就像每个进程都有一个进程号一样, 每个线程也有一个线程号
进程号在整个系统中是唯一的, 但线程号不同, 线程号只在它所属的进程环境中有效
进程号用 pid_t 数据类型表示, 是一个非负整数。 线程号则用 pthread_t 数据类型来表示
有的系统在实现 pthread_t 的时候, 用一个结构体来表示, 所以在可移植的操作系统实现不能把它做为整数处理
线程的创建
与 fork 不同的是 pthread_create 创建的线程不与父线程在同一点开始运行,而是从指定的函数开始运行,该函数运行完后,该线程也就退出了
线程依赖进程存在的,如果创建线程的进程结束了,线程也就结束
线程函数的程序在 pthread 库中,故链接时要加上参数-lpthread
#include <pthread.h>
/*
*功能:
* 创建一个线程
*参数:
* thread: 线程标识符地址
* attr: 线程属性结构体地址
* start_routine: 线程函数的入口地址
* atg: 传给线程函数的参数
*return:
* 成功:0
* 失败:非0
*/
int pthread_reate(pthread_t *thread,
const pthread_addr_t *attr,
void *(*start_routine)(void *),
void *arg);
验证多线程实现多任务, 及线程间共享全局变量
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
int var = 8;
void *thread_1(void *arg);
void *thread_2(void *arg);
int main(int argc, char *argv[])
{
pthread_t tid1;
pthread_t tid2;
//创建俩个线程
pthread_create(&tid1, NULL, thread_1, NULL);
pthread_create(&tid2, NULL, thread_2, NULL);
while(1);
return 0;
}
void *thread_1(void *arg)
{
while(1)
{
printf("this is my new thread1 var++\n");
var++;
sleep(1);
}
return NULL;
}
void *thread_2(void *arg)
{
while(1)
{
printf("this is my new thread_2 var = %d\n",var);
sleep(1);
}
return NULL;
}
验证线程函数传参
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
void *thread_1(void *arg);
void *thread_2(void *arg);
int main(int argc, char *argv[])
{
pthread_t tid1;
pthread_t tid2;
int test = 100;
// double test = 100;
//创建线程
pthread_create(&tid1, NULL, thread_1, (void*)test);
pthread_create(&tid2, NULL, thread_2, (void *)(&test));
//test++;
while(1);
return 0;
}
//传参方法
void *thread_1(void *arg)
{
int rec = 0;
sleep(1);
rec = (int)(arg);
printf("new thread1 arg = %d\n",rec);
return NULL;
}
void *thread_2(void *arg)
{
int rec = 0;
sleep(1);
rec = *((int *)arg);
printf("new thread2 arg = %d",rec);
return NULL;
}
man 3 pthread_create
gcc -pthread xxx