概述
1 线程(pthread_t)
1.1 创建、等待、终止线程
-
线程创建
#include <pthread.h> /**@param tidp -新创建的线程ID指向的内存单元。 * @param attr -线程属性,默认为NULL * @param start_rtn -线程函数 * @param arg -线程函数的传入参数 * @return 0 创建成功 * -1 创建失败 */ int pthread_create( pthread_t *restrict tidp, const pthread_attr_t *restrict attr, void *(*start_rtn)(void *), void *restrict arg );
-
等待线程返回
/**@param tid -需要等待的线程(不能是分离线程) * @param status -线程的返回值 * @return 0 正常返回 * ESRCH 没有找到与给定的线程ID 相对应的线程。 * EDEADLK 将出现死锁,如一个线程等待其本身,或者线程A和线程B 互相等待。 * EINVAL 与给定的线程ID相对应的线程是分离线程。 * @return */ int pthread_join( pthread_t tid, void **status);
-
提前终止线程
/**@param rertval -返回值,提前终止也可以返回值 * @note 该语句在线程函数里使用,如 pthread_exit(0); */ void pthread_exit(void *retval);
-
例子
#include <stdlib.h> #include <stdio.h> #include <errno.h> #include <pthread.h> static void pthread_func_1 (void); static void pthread_func_2 (void); int main (int argc, char** argv) { pthread_t pt_1; pthread_t pt_2; pthread_attr_t attr; int ret = 0; /*初始化属性线程属性*/ pthread_attr_init(&attr); pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM); // 与系统抢占资源 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); // 分离状态 ret = pthread_create (&pt_1, &attr, pthread_func_1, NULL); // pt_1 设置以上属性 if (ret != 0) { perror ("pthread_1_create"); } ret = pthread_create (&pt_2, NULL, pthread_func_2, NULL); // pt_2 默认属性 if (ret != 0) { perror ("pthread_2_create"); } pthread_join (pt_2, NULL); // 等待 pt_2 返回 return 0; } static void pthread_func_1(void) { for (int i = 0; i < 6; i++) { printf ("This is pthread_1.n"); if (i == 2) { pthread_exit (0); } } return ; } static void pthread_func_2(void) { for (int i = 0; i < 3; i ++) { printf ("This is pthread_2.n"); } return; }
1.2 设置线程属性
在上面的例子中,创建线程函数 pthread_create()
的第二个参数是描述线程的属性,如果为 NULL
,则为默认属性,也可以手动设置属性,使用结构体 pthread_attr_t,后面的描述都是配置这个结构体:
typedef struct
{
int
detachstate;
// 线程的分离状态
int
schedpolicy;
// 线程调度策略
struct sched_param
schedparam;
// 线程的调度参数
int
inheritsched;
// 线程的继承性
int
scope;
// 线程的作用域
size_t
guardsize;
// 线程栈末尾的警戒缓冲区大小
int
stackaddr_set;
void *
stackaddr;
// 线程栈的位置
size_t
stacksize;
// 线程栈的大小
} pthread_attr_t;
-
初始化
#include <pthread.h> int pthread_attr_init(pthread_attr_t *attr); // 初始化 int pthread_attr_destroy(pthread_attr_t *attr); // 去除初始化
-
线程分离
#include <pthread.h> int pthread_attr_getdetachstate(const pthread_attr_t * attr, int * detachstate); int pthread_attr_setdetachstate(pthread_attr_t * attr, int detachstate); //参数:attr:线程属性变量 // detachstate:分离状态属性 // PTHREAD_CREATE_DETACHED 分离状态启动 // PTHREAD_CREATE_JOINABLE 正常启动线程 //若成功返回0,若失败返回-1。
-
线程的继承性
继承性决定调度的参数是从创建的进程中继承还是使用在schedpolicy
和schedparam
属性中显式设置的调度信息。#include <pthread.h> int pthread_attr_getinheritsched(const pthread_attr_t *attr,int *inheritsched); int pthread_attr_setinheritsched(pthread_attr_t *attr,int inheritsched); //参数: //attr 线程属性变量 //inheritsched 线程的继承性 // PTHREAD_INHERIT_SCHED: 新的线程继承创建线程的策略和参数! // PTHREAD_EXPLICIT_SCHED:新的线程继承策略和参数来自于schedpolicy和schedparam属性中显示设置的调度信息! //若成功返回0,若失败返回-1。
-
调度策略
int pthread_attr_getschedpolicy(const pthread_attr_t *, int * policy) int pthread_attr_setschedpolicy(pthread_attr_*, int policy) //参数: //attr 线程属性变量 //policy 调度策略 // SCHED_FIFO :先进先出 // SCHED_RR :轮转法 // SCHED_OTHER :其他方法,不支持优先级 //若成功返回0,若失败返回-1。
-
调度参数
int pthread_attr_getschedparam(const pthread_attr_t *,struct sched_param *); int pthread_attr_setschedparam(pthread_attr_t *,const struct sched_param *); //参数: // attr 线程变量属性 // param sched_parm 结构体 //若成功返回0,若失败返回-1。 // 用到的结构体 // /usr/include/bits/sched.h struct sched_param { int sched_priority; // 参数的本质就是优先级,大的权值对应高的优先级! }; // 获取可以设置的最大、最小优先级 #include <pthread.h> int sched_get_priority_max( int policy ); int sched_get_priority_min( int policy ); //参数: // policy 调用策略,也就是说对于不同的策略的值是不一样的! // _max: 系统支持的优先级的最大值 // _min : 系统支持的优先级的最小值
-
线程的作用域
作用域控制线程是否在进程内或在系统级上竞争资源#include <pthread.h> int pthread_attr_getscope( const pthread_attr_t * attr, int * scope ); int pthread_attr_setscope( pthread_attr_t*, int scope ); // 参数: // attr 线程属性变量 // scope 线程的作用域 // PTHREAD_SCOPE_PROCESS (进程内竞争资源) // PTHREAD_SCOPE_SYSTEM (系统级竞争资源) // 若成功返回0,若失败返回-1。
-
线程栈的大小
int pthread_attr_getstacksize(const pthread_attr_t *,size_t * stacksize); int pthread_attr_setstacksize(pthread_attr_t *attr ,size_t *stacksize); // 参数: // attr 线程属性变量 // stacksize 堆栈大小 // 若成功返回0,若失败返回-1。
-
线程栈的地址
#include <pthread.h> int pthread_attr_getstackaddr(const pthread_attr_t *attr,void **stackaddf); int pthread_attr_setstackaddr(pthread_attr_t *attr,void *stackaddr); // 参数:attr 线程属性变量 // stackaddr 堆栈地址 // 若成功返回0,若失败返回-1。
-
警戒缓冲区
线程属性guardsize控制着线程栈末尾之后以避免栈溢出的扩展内存大小。这个属性默认设置为PAGESIZE个字节。可以把guardsize线程属性设为0,从而不允许属性的这种特征行为发生:在这种情况下不会提供警戒缓存区。同样地,如果对线程属性stackaddr作了修改,系统就会认为我们会自己管理栈,并使警戒栈缓冲区机制无效,等同于把guardsize线程属性设为0。
#include <pthread.h> int pthread_attr_getguardsize(const pthread_attr_t *restrict attr,size_t *restrict guardsize); int pthread_attr_setguardsize(pthread_attr_t *attr ,size_t *guardsize); // 若成功返回0,若失败返回-1。
2 线程锁
2.1 互斥锁
-
创建
可以静态创建:#include <pthread.h> pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
可以动态创建:
#include <pthread.h> pthread_mutex_t mutex; int pthread_mutex_init(pthread_mutex_t*mutex, const pthread_mutexattr_t * attr); // 其中: // mutex:所需创建的锁; // attr:创建锁的属性。一般默认为NULL,表示线程间共享;
-
操作
int pthread_mutex_lock(pthread_mutex_t*mutex); // 加锁 int pthread_mutex_trylock(pthread_mutex_t *mutex); // 尝试加锁,成功返回 0,否则返回 -1 int pthread_mutex_timedlock(pthread_mutex_t *__restrict __mutex, const struct timespec *__restrict __abstime); // 在时间范围内加锁,成功返回 0,否则返回 -1 int pthread_mutex_unlock(pthread_mutex_t *mutex); // 解锁
-
销毁
int pthread_mutexattr_destroy (pthread_mutex_t *mutex);
-
例子
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
pthread_mutex_t mutex; //定义锁
void *tfn(void *arg) {
while (1) {
pthread_mutex_lock(&mutex); //加锁
printf("hello ");
sleep(1); /*模拟长时间操作共享资源,导致cpu易主,产生与时间有关的错误*/
printf("worldn");
pthread_mutex_unlock(&mutex); //解锁
sleep(1);
//睡眠,释放cpu
}
return NULL;
}
int main(void) {
pthread_t tid;
pthread_mutex_init(&mutex, NULL); //初始化锁 mutex==1
pthread_create(&tid, NULL, tfn, NULL);
while (1) {
pthread_mutex_lock(&mutex); //加锁
printf("HELLO ");
sleep(1);
printf("WORLDn");
pthread_mutex_unlock(&mutex); //解锁
sleep(1);
}
pthread_mutex_destroy(&mutex); //销毁锁
return 0;
}
最后
以上就是欢喜背包为你收集整理的Linux 线程和线程锁的全部内容,希望文章能够帮你解决Linux 线程和线程锁所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复