加入收藏 | 设为首页 | 会员中心 | 我要投稿 广州站长网 (https://www.020zz.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 服务器 > 搭建环境 > Linux > 正文

linux多线程

发布时间:2023-01-05 05:32:02 所属栏目:Linux 来源:互联网
导读: 多线程:所有程序并发运行,多条路径可以同时执行
多线程包括:理解线程并发、线程同步方法、线程安全概念
线程指:进程内部得一条执行路径(从主函数的第一行代码到最后一行)
主线程:ma

多线程:所有程序并发运行,多条路径可以同时执行

多线程包括:理解线程并发、线程同步方法、线程安全概念

线程指:进程内部得一条执行路径(从主函数的第一行代码到最后一行)

主线程:main子线程:线程函数 比如:fun....

linux线程 进程_linux 线程_linux 线程 进程

进程指:一个正在运行的程序

在linux平台创建线程,是内核提供的

头文件#include

注意编译的时候要加 -lpthread

pthread_create(线程idlinux 线程,默认的属性可以不设置为NULLL,参数函数); 创建线程

linux 线程 进程_linux 线程_linux线程 进程

子线程如下图

linux线程 进程_linux 线程_linux 线程 进程

有些时候主线程会不等子线程运行完毕就退出进程,导致子线程来不及打印,可以加个睡眠,但这样效率太低了!!

pthread_join(id,二级指针); 等子线程会在执行后等待子线程结束,子线程会返回给它一个值

linux 线程_linux 线程 进程_linux线程 进程

pthread_exit(); 退出子线程 参数一个字符串,子线程结束后会返回给主线程

linux 线程_linux 线程 进程_linux线程 进程

主线程、子线程并发运行

linux 线程 进程_linux线程 进程_linux 线程

运行结果我们可以看出,主线程和子线程是并发运行的,所以打印出的数字不是按顺序打印的,

在极短的时间内,五个线程同时被创建

linux 线程_linux 线程 进程_linux线程 进程

当我们处理器为双核或者更多时,打印5000会出现4999的情况,这是因为在某一个时间里,两个处理器同时处理了同一个值加一,这种情况在处理器越多的情况下越容易发生数值重合加一

这种情况叫做并发,并发是一种特殊的并行

并发:同一时刻可能只有一个线程在执行,

并行:同一时刻可能有多个线程在执行,一个处理器不可能出现并行,至少两个

线程同步

四种方法:1.互斥锁 2.使用信号量 3.条件变量 4.读写锁

一、信号量解决

我们设置五个线程,让他们累加到5000,通过设置信号量,让创建的线程执行P\V操作后,可以实现线程同步,即使多个处理器也不会出现小于5000的数

头文件#include

sem_t sem;//定义一个信号量

linux 线程 进程_linux线程 进程_linux 线程

sem_init(传入定义的信号量,是否在进程间共享,初始值)

linux线程 进程_linux 线程 进程_linux 线程

sem_wait(信号量地址) //线程的p操作

sem_post(信号量地址) //线程的v操作

linux 线程_linux线程 进程_linux 线程 进程

sem_destroy(信号量地址); //销毁信号量

二、互斥锁

一个线程再用资源时先加个锁,当用完时再解锁,别的线程再使用

pthread_mutex_t mutex; //创建锁

pthread_mutex_init(定义锁变量,初始化,锁属性一般为NULL); //初始化

pthread_mutex_lock(锁地址) //加锁

pthread_mutex_unlock(锁地址) //解锁

pthread_mutex_dsetroy(锁地址) //销毁锁

三、读写锁

一般用于读较多的情况下

pthread_rwlock_t 变量名 //创建锁变量

pthread_rwlock_init(锁变量地址,属性一般给NULL) //锁初始化

pthread_rwlock_rdlock() //读锁

linux线程 进程_linux 线程_linux 线程 进程

pthread_rwlock_wrlock() //写锁

linux线程 进程_linux 线程 进程_linux 线程

pthread_rwlock_unlock() //解锁

pthread_rwlock_destroy() //销毁锁

所谓的临界区一定要赶紧使用完后释放,让别人也继续使用,所以不能有过多的等待

四、条件变量 (提供一种线程间通知的机制)

互斥锁是用于同步线程对共享数据的访问,条件变量是用于在线程之间同步共享数据的值

pthread_cond_t cond; //创建条件变量,同时我们也配合着锁使用,锁是为了保证条件变量可以正常进行

pthread_cond_init(变量,属性一般给NULL) //初始化

linux 线程 进程_linux线程 进程_linux 线程

pthread_cond_destroy(变量) //销毁

pthread_cond_broadcast(变量) //唤醒所有在条件变量上等待的线程

linux 线程 进程_linux线程 进程_linux 线程

pthread_cond_signal(变量) //唤醒某一个在条件变量上等待的线程

linux线程 进程_linux 线程 进程_linux 线程

pthread_cond_wait(条件变量,互斥锁) // 为了不让两个线程同时进,所以要加锁

wait做了两步操作:1.把线程放到等待队列上等着被唤醒 2.对互斥锁解锁

当pthread_cond_wait()成功将线程放队列上时解锁,再将锁锁上,因为不想再进或出时被唤醒

linux 线程 进程_linux 线程_linux线程 进程

strtok不能再线程中使用!!!!!两个线程都调用的话strtok里面的静态指针或者全局指针变量就会失效,定位会出错!!! 必须使用线程安全的版本 strtok_r(数组地址,分隔符,指针地址) 线程安全:多线程程序无论 调度顺序先后,都可以保证得到一个正确的一致的结果,我们就称为线程安全,正确性保证就是安全

如何保证线程安全:1.线程同步 2.使用线程安全函数(可重入函数,比如:函数名_r)

多线程程序如果使用fork 怎么理解?

当线程使用fork时只会产生一条子进程,不管父进程有多少条执行路径,子进程都只启用fork所在的那条路径,其他路径都停止,资源都可以使用的

linux线程 进程_linux 线程 进程_linux 线程

linux 线程 进程_linux 线程_linux线程 进程

结果能看出,fork后子进程只产生了一条main进程,在哪一条路径里fork,就只在哪一条路径上产生一个子进程

如果fork在产生子进程时,其他线程没有加锁,则子进程也没加锁,反之其他线程正在用加锁了,则子进程也有锁

fork只能在没人用锁的使用在复制,当我们在子线程用锁的时候,如下图,去fork就会发现,fork复制的是和子线程一样的锁,但是此时锁已经被子线程给锁住了,所以在fork完的路径里,子进程想要执行pthread_mutex_lock时就会发现被阻塞住了,因为锁已经被子线程锁上了,子进程复制的是被锁上的锁,不能再上一次锁

linux 线程_linux 线程 进程_linux线程 进程

linux 线程 进程_linux线程 进程_linux 线程

多线程程序如何使用fork?

为了解决上面的问题,系统提供了一个方法 pthread_atfork();参数为三个函数指针,分别指向三个函数,分别为:void *prepare(void);它将在fork调用之前被执行,在父进程中执行的用来锁住所有父进程中的互斥锁。 void *parent(void);它将在fork调用创建出子进程之后,在返回之前,在父进程中被执行,作用是释放所有被prepare锁住的互斥锁。 void *child(void); 是在fork返回之前,在子进程中被执行,和parent一样,child作用也是用于释放所有被prepare锁住的互斥锁,该函数成功返回时0,返回失败是错误码。

linux 线程 进程_linux 线程_linux线程 进程

linux 线程 进程_linux线程 进程_linux 线程

linux线程 进程_linux 线程_linux 线程 进程

线程属性

linux线程 进程_linux 线程_linux 线程 进程

setdetachstate相当于pthread_join();

使用时把pthread_create();中第二个参数改为&attr

linux 线程_linux 线程 进程_linux线程 进程

线程的实现: 1.纯粹用户级线程,由用户管理创建调度,内核不参与感知不到,优点开销小,缺点无法使用多个处理器,只能实现并发! 2.纯粹内核级内核创建并有内核来管理,优点可以使用多个处理器 ,缺点开销大,但可以实现真正意义上的并行! 3.组合级,用户和内核组合对线程的管理 多线程调试

info threads //查看线程信息,当被调试的主线程,线程id为*1

thread +线程id号 // 切换线程

面试问题

1.线程和进程的区别

答:线程指进程雷部的一条执行路径(序列) 进程:一个正在运行的程序

2.线程的实现

答:纯粹用户级线程,由用户管理创建调度,内核不参与感知不到,优点开销小,缺点无法使用多个处理器,只能实现并发!

纯粹内核级内核创建并有内核来管理,优点可以使用多个处理器 ,缺点开销大,但可以实现真正意义上的并行!

组合级,用户和内核组合对线程的管理

3.线程并发运行

答:举例:当我们处理器为双核或者更多时,打印5000会出现4999的情况,这是因为在某一个时间里,两个处理器同时处理了同一个值加一,这种情况在处理器越多的情况下越容易发生数值重合加一

4.线程通讯的同步方法

答:设置信号量、互斥锁、条件变量、读写锁

5.线程安全

答:多线程程序无论 调度顺序先后,都可以保证得到一个正确的一致的结果,我们就称为线程安全,正确性保证就是安全,使用线程同步和使用线程安全函数(可重入函数,比如:函数名_r)来实现线程安全

(编辑:广州站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!