Linux线程(线程、互斥锁、条件)

这几天学习了Linux 进程,现在学习线程。
一个进程在同一时刻只做一件事情。有了多个控制线程后,在程序设计时可以把进程设计成在同一时刻做不止一件事,每个线程各自处理独立的任务。
一个程序至少个进程,一个进程至少有一个线程。

一、线程

1、创建线程(成功返回0,否则返回错误编号)

原型:
int pthread_create**(pthread_t *restrict **tidp**, const pthread_attr_t *restrict attr, **void *(*start_rtn)(void *)**, void *restrict **arg);
**参数:**
**1.tidp**:指向线程标识符的指针。
**2.attr**:设置线程属性(默认为**NULL****3.(*start_rtn)(void *)**:是一个函数指针,线程运行函数的起始地址。
**4.arg**:运行函数的参数。

**

tidp指向的单元被设置为新创建线程的线程ID。attr参数为线程属性,默认为NULL,新创建的线程是从rtn开始运行的,是一个函数指针,只有一个无类型指针参数arg**,如果传递参数不止一个,那需要定义结构体,把结构体地址作为arg传入。

2、线程等待(成功返回0,否则返回错误编号)

原型:int pthread_join(pthread_t thread, void **rval_ptr);
参数:
thread: 线程标识符,即线程ID,线程名,标识唯一线程。
retval: 用户定义的指针,用来存储被等待线程的返回值。默认为NULL,不关心退出状态

如果线程被取消,由rval_ptr指定的内存单元就置为PTHREAD_CANCELED。以阻塞方式等待thread指定线程结束,参数thread是需要等待的线程ID,rval_ptr是用户定义的指针存储被等待线程的返回值

3、线程退出

原型:int pthread_exit(void *rval_ptr);
参数:是个空类型的指针保存的是线程退出以后的返回值,进程中的其他线程可以通过调用pthread_join函数访问到这个指针,不需要返回也可以直接NULL

4、线程的ID

原型:pthread_t pthread_self(void);
// 返回:调用线程的ID

5.线程脱离

原型:int pthread_detach(pthread_t tid);
参数:tid:线程标识符

pthread_join()函数的替代函数,可回收创建时detachstate属性设置为PTHREAD_CREATE_JOINABLE的线程的存储空间。
该函数不会阻塞父线程。pthread_join()函数用于只是应用程序在线程tid终止时回收其存储空间。如果tid尚未终止,pthread_detach() 不会终止该线程。当然**pthread_detach(pthread_self())**也是可以的。

6.线程ID的比较(若相等则返回非0值,否则返回0)

原型:int pthread_equal(pthread_t tid1, pthread_t tid2)

对于线程ID比较,为了可移植操作,我们不能简单地把线程ID当作整数来处理,因为不同系统对线程ID的定义可能不一样。我们应该要用上边的函数。

代码实现一下创建一个线程,然后打印改线程的ID,同时main函数也打印一下线程ID。

代码:
在这里插入图片描述
运行结果:
在这里插入图片描述
注意文明在编译的时候要加上-lpthread

二、与互斥锁相关API

互斥量就是一个锁。有加锁销毁锁操作。加锁跟解锁包含起来的我们叫共享资源。当我们想运行到某个线程中的内容时候,就想单单让该线程的内容执行完再执行其他线程,就要用到互斥锁。

1.创建互斥锁(成功返回0,否则返回错误编号)

原型:int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr);
attr:NULL为默认属性。

pthread_mutex_init()函数是以动态方式创建互斥锁的,参数attr指定了新建互斥锁的属性。如果参数attr为空(NULL),则使用默认的互斥锁属性,默认属性为快速互斥锁 。

2.销毁互斥锁(成功返回0,否则返回错误编号)

原型:int pthread_mutex_destroy(pthread_mutex_t *mutex); //mutex 指向要销毁的互斥锁的指针

3.加锁(成功返回0,否则返回错误编号)

原型:int pthread_mutex_lock(pthread_mutex_t *mutex);

4.解锁(成功返回0,否则返回错误编号)

int pthread_mutex_unlock(pthread_mutex_t *mutex);

如果线程不希望被阻塞,它可以使用pthread_mutex_trylock尝试对互斥量进行加锁。如果调用pthread_mutex_trylock时互斥量处于未锁住状态,那么pthread_mutex_trylock将锁住互斥量,不会出现阻塞并返回0,否则pthread_mutex_trylock就会失败,不能锁住互斥量,而返回EBUSY。

我们代码用一下互斥锁这么API。
让一个线程每隔1秒打印线程ID(一共打印5次),让一个线程每隔一秒打印ID(一共打印3次)。我们用互斥锁的作用就是能让一个线程先执行完再执行另一个线程。这就是互斥锁的作用

代码:
在这里插入图片描述
在这里插入图片描述
运行结果:
在这里插入图片描述

三、与条件变量相关API

上面说了互斥锁,其实只能说运行到某个线程,能把这么线程的内容运行完再运行其他线程,但不能控制到我想某个线程先运行,某个线程先等待。那么下面有几个API就能控制线程谁先运行,谁等待。

1.创建条件/初始化条件(成功返回0,否则返回错误编号)

原型:int pthread_cond_init(pthread_cond_t *restrict cond, const pthread_condattr_t *restrict attr);

参数:
cond:是一个指向结构pthread_cond_t的指针
attr:默认NULL
除非需要创建一个非默认属性的条件变量,否则pthread_cont_init函数的attr参数可以设置为NULL
静态创建:
pthread_cond_t cond = PTHREAD_COND_INITIALIZER

2.销毁条件(成功返回0,否则返回错误编号)

原型:int pthread_cond_destroy(pthread_cond_t cond);
cond:指向pthread_cond_t结构的指针。

3. 等待(成功返回0,否则返回错误编号)

原型:int pthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex);
作用:让线程阻塞

4.触发(成功返回0,否则返回错误编号)

原型:int pthread_cond_signal(pthread_cond_t cond);
作用:唤醒处于阻塞的线程。

我们用代码使用一下上面的API,比如让一个线程从0不断的+1,等加到3,我们让另一个线程打印并且变为0。不断循环,循环3次。这样就可以主动控制某个线程先执行了。

代码:
在这里插入图片描述
在这里插入图片描述
运行结果:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

皮卡丘吉尔

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值