我是靠谱客的博主 欢喜背包,最近开发中收集的这篇文章主要介绍Linux 线程和线程锁,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

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。
    
  • 线程的继承性
    继承性决定调度的参数是从创建的进程中继承还是使用在 schedpolicyschedparam 属性中显式设置的调度信息。

    #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 线程和线程锁所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(49)

评论列表共有 0 条评论

立即
投稿
返回
顶部