Linux中线程相关API函数的定义及使用

1. 线程的创建与销毁:

1.1 函数原型:

1.1.1 pthread_create:

#include <pthread.h>
int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine)(void *), void *arg);

函数作用:
pthread_create函数用于创建除主线程以外的其他线程。

当一个程序由exec启动执行时,称为 初始线程(initial thread)主线程(main thread) 的单个线程就创建了。 其余线程则由 pthread_create 函数创建。

参数:
pthread_t* :用于返回新创建的线程的tid;
pthread_attr_t* :用于传入线程设置属性,包括:优先级、初始栈大小、是否成为一个守护线程 等,通常情况下使用默认配置传入NULL;
void* (*start_routine):由该线程执行的函数;
void *arg: 该线程执行函数的参数。

返回值:
成功返回0, 失败返回错误码(正数):EAGAIN/EINVAL/EPERM
(1)EAGAIN:没有足够的资源创建线程;
(2)EINVAL:attr线程属性参数不正确;
(3)EPERM:no permission,没有权限

注意pthread_create 与套接字函数及大多数系统调用“出错时返回-1并设置errno”的做法并不相同,pthread_create出错时直接返回正数错误码。

1.1.2 pthread_join:

#include <pthread.h>
int pthread_join(pthread_t tid, void **retval);

函数作用:
用于等待一个给定线程的终止,参数 tid用于指定要等待线程的tid,**retval指针用于存储来自所等待线程的返回值(一个指向某个对象的指针)。

返回值:
成功返回0,失败返回错误码:EDEADLOCK/EINVAL/ESRCH
(1)EDEADLOCK:死锁,例如两个线程互相join等待对方
注:pthread_join是一个阻塞函数,要一直等到其所等待的线程结束后才能继续向下执行,因此如果发生两个线程互相join等待彼此时是会发生死锁的
(2)EINVAL:参数tid所指定的线程不是joinable态(tid若处于detach则不能当做被join等待的对象)
或者:另有一个线程正在join等待本线程,及join不能嵌套
(3)ESRCH:参数tid所指定的线程找不到,即这个线程不存在。

1.1.3 pthread_detach:

#include <pthread.h>
int pthread_detach(pthread_t tid);

函数作用:
将线程状态置为“脱离的(detached)”。

返回值:
成功返回0,失败返回错误码:EINVAL/ESRCH
(1)EINVAL:there is a not a joinable thread. 不是joinable的线程,不能调用detach
(2)ESRCH:No thread with the ID could be found. 参数tid指定的线程不存在

1.1.4 pthread_exit:

#include <pthread.h>
void pthread_exit(void *retval);

函数作用:
函数显式的终止的方法是调用pthread_exit。
如果此线程的状态是joinable,则调用pthread_exit时传入的参数 *retval 将传回给 调用了pthread_join正在等待它退出的线程。

注意 *retval 不能指向线程的局部对象,因为当线程终止时局部对象也将被释放。

返回值:
无返回值,通过参数*retval返回一个字符串,
返回到给正在调用pthread_join等待它的线程
(返回到pthread_join第二个参数中)

1.1.5 pthread_cancel:

#include <pthread.h>
int pthread_cancel(pthread_t tid);

函数作用:
通过在一个线程中调用pthread_cancel,可以终止tid指定的另一个线程。

返回值:
成功返回0,失败返回错误码:ESRCH
(1)ESRCH:No thread with the ID could be found.
参数thread指定的线程找不到,不存在

1.1.6 pthread_self:

#include <pthread.h>
pthread_t pthread_self(void);

函数作用:
每个线程都有一个在所属进程内标识自身的ID。线程ID由 pthread_self 返回。

1.2 线程状态:joinable与detached:

一个线程的状态只能有两种:要么是“可汇合的(joinable)”,要么是“脱离的(detached)”。

线程的默认属性是joinable。

joinable: 当一个joinable的线程终止时,它的线程ID和退出状态将留存到另一个线程对它调用pthread_join(往往是main主线程);
detached: 而当一个线程detach脱离后,当它们终止时,所有相关资源都会由系统来自动释放(如线程ID、线程栈空间、线程退出状态等)。

一个调用了detach的线程不能被其他线程join等待。

如果一个线程需要知道另一个线程什么时候终止,那么就必须保持第二个线程的joinable可汇合状态,并在本线程调用pthread_join等待第二个线程退出。

示例:
通过pthread_join在一个线程中获取另一个线程何时退出:

#include <stdio.h>
#include <pthread.h>

void* start_routine(void* arg) {
    pthread_exit(NULL);
}

int main() {
    pthread_t tid;
    pthread_create(&tid, NULL, start_routine, NULL);

    pthread_join(tid, NULL);
    printf("thread is exited.\n");

    return 0;
}

1.3 一个线程终止(被终止)的三种方式:

方式一: 线程内调用 pthread_exit

如果不带参数:pthread_exit(NULL) 则直接退出;
如果带参数:pthread_exit(*str); 则将字符串str拷贝到 pthread_join(tid, &ptr)的ptr中。

方式二: 线程函数运行完毕后返回:

启动线程的函数(即 pthread_create的第三个参数 void*)(* start_routine))可以返回,返回值是一个 void* 类型的指针,它的返回值就是相应线程的终止状态。

方式三: 调用 pthread_cancel 终止另外一个线程:

线程调用 pthread_cancel 函数给tid线程发送一个cancel终止信号,tid线程收到终止信号后并不会立即终止,而是要看tid线程对cancel信号的处理方式:
忽略 / 立即终止 / 运行至取消点
(取消点:根据POSIX的定义,所有可能会引起线程阻塞的系统调用都是取消点,
例如:pthread_join、pthread_cond_wait、read、write、sem_wait 等)

方式四: 进程退出:

如果进程的main函数返回 或者 任何线程 调用了exit,整个进程就终止,其中包括它的任何线程。

PS: 并不是一定要等待主线程退出时整个进程才会退出,实际上进程内的任何一个线程调用了exit()函数都会使进程退出。

2. 线程互斥锁和条件变量:

#include <pthread.h>

//创建:
int pthread_mutex_init(pthread_mutex_t *restrict_mutex, 
					const pthread_mutexattr_t *restrict_attr);
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
//销毁:
int pthread_mutex_destroy(pthread_mutex_t *mutex);
//加锁:
int pthread_mutex_lock(pthread_mutex_t *mutex);
//解锁:
int pthread_mutex_unlock(pthread_mutex_t *mutex);


//初始化信号量:
int pthread_cond_init(pthread_cond_t *cond, 
					pthread_cond_attr_t *cond_attr);
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
//销毁信号量:
int pthread_cond_destroy(pthread_cond_t *cond);
//等待信号量:
int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex);
//唤醒一个等待队列中的线程:
int pthread_cond_signal(pthread_cond_t *cond);
//唤醒等待队列中的所有线程:
int pthread_cond_broadcast(pthread_cond_t *cond);

关于线程信号量的深入理解:

(1)pthread_cond_wait 实现了一个阻塞队列,每个等待mutex的线程都放在这个等待队列中;
所以 pthread_cond_signal 就是从等待队列中取出一个线程唤醒,pthread_cond_broadcast 则是将等待队列中的所有线程全部唤醒。
(2)pthread_cond_wait 函数内部先对 mutex unlock 解锁,然后再对 mutex lock 加锁。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值