线程的概念

     每个进程都拥有自己的数据段、代码段和堆栈段,这就造成进程在进行创建、切换、撤销操作时,需要较大的系统开销

     为了减少系统开销, 从进程中演化出了线程

     线程存在于进程***享进程的资源

    线程是进程中的独立控制流, 由环境(包括寄存器组和程序计数器) 和一系列的执行指令组成

  每个进程有一个地址空间和一个控制线程

线程和进程的比较

   调度:

       线程是 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