Linux系统编程之线程

一、概述

  1. 典型的Unix和Linux进程可以看成一个控制的线程,这个进程在同一时刻只做一件事情;

  1. 当Unix和Linux进程有了多个控制线程之后,进程在同一时刻就不只做一件事情,每个线程都有各自处理的任务;

  1. 进程在程序运行的过程,是系统分配资源的基本单位,在线程设计的系统中,进程本身并不是基本运行的单位,而是线程的容器;

  1. 线程是操作系统能够进行运算调度的最小单位;

  1. 一个进程中可以并发多个线程,每条线程并行执行不同的任务。

二、创建子线程

  1. API原型

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

  1. API的参数

  • pthread_t *thread:子线程入口地址,创建一个pthread_t类型的子线程;

  • const pthread_attr_t *attr:线程的属性,一般使用NULL,具体可以在man手册查看;

  • void *(*start_routine) (void *):子线程入口函数,注意函数的类型;

  • void *arg:子函数的入口参数;

  • 返回值:成功返回0,错误返回-1,并设置errno。

  1. API的demo_1(创建子线程,并获取线程ID)

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

void *fun1(void *arg){
    printf("task : thread is create\n");
    printf("task : %ld \n",(unsigned long)pthread_self());
    printf("task : param is %d \n",*((int *)arg));
}

int main()
{
    pthread_t task;
    int ret;
    int param = 100;

    ret = pthread_create(&task, NULL, fun1, (void *)&param);

    //返回值为0时创建成功
    if(ret == 0){
        printf("main : create success\n");
    }
    printf("main : %ld\n",(unsigned long)pthread_self());
    pthread_join(task, NULL);//等待子线程执行完成退出

    return 0;
}

  1. demo_1的运行

  1. API的demo_2(创建子线程,执行完子线程,并返回一个整数)

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

void *fun1(void *arg){
    static int ret = 10;        //退出码要使用静态变量
    printf("task : thread is create\n");
    printf("task : %ld \n",(unsigned long)pthread_self());
    printf("task : param is %d \n",*((int *)arg));
    pthread_exit((void *)&ret);
}

int main()
{
    pthread_t task;
    int ret;
    int param = 100;
    int *pret = NULL;
    ret = pthread_create(&task, NULL, fun1, (void *)&param);

    //返回值为0时创建成功
    if(ret == 0){
        printf("main : create success\n");
    }
    printf("main : %ld\n",(unsigned long)pthread_self());
    pthread_join(task, (void **)&pret);//等待子线程执行完成退出
               //子线程退出的状态码
    printf("main : t1 quit : %d\n",*pret);

    return 0;
}

  1. demo_2的运行

  1. API的demo_3(创建子线程,执行完子线程,并返回字符串)

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

void *fun1(void *arg){
    static char *p = "task is run out";        //退出码要使用静态变量
    printf("task : thread is create\n");
    printf("task : %ld \n",(unsigned long)pthread_self());
    printf("task : param is %d \n",*((int *)arg));
    pthread_exit((void *)p);
}

int main()
{
    pthread_t task;
    int ret;
    int param = 100;
    char *pret = NULL;
    ret = pthread_create(&task, NULL, fun1, (void *)&param);

    //返回值为0时创建成功
    if(ret == 0){
        printf("main : create success\n");
    }
    printf("main : %ld\n",(unsigned long)pthread_self());
    pthread_join(task, (void **)&pret);//等待子线程执行完成退出
               //子线程退出的状态码
    printf("main : t1 quit : %s\n",pret);

    return 0;
}

  1. demo_3的运行

三、多个线程共享内存

  1. demo

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

void *fun1(void *arg){
    printf("task_1 : thread is create\n");
    printf("task_1 : %ld \n",(unsigned long)pthread_self());
}

void *fun2(void *arg){
    printf("task_2 : thread is create\n");
    printf("task_2 : %ld \n",(unsigned long)pthread_self());
}

int main()
{
    pthread_t task_1;
    pthread_t task_2;
    int ret;
    int param = 100;

    ret = pthread_create(&task_1, NULL, fun1, (void *)&param);
    if(ret == 0){
        printf("main : task_1 create success\n");
    }
    
    ret = pthread_create(&task_2, NULL, fun2, (void *)&param);
    if(ret == 0){
        printf("main : task_2 create success\n");
    }

    printf("main : %ld\n",(unsigned long)pthread_self());
  
    while(1);//防止主线程退出

    return 0;
}

  1. demo的运行

  1. 从运行结果来看,并不存在先执行线程1,再执行线程2,这里两个线程为同等优先级,两个线程会相互争夺CPU的使用权;

四、互斥量限制共享资源

  1. API原型

SYNOPSIS
    #include <pthread.h>
    
    //创建锁   
    int pthread_mutex_init(pthread_mutex_t *mutex,
                           const pthread_mutexattr_t  *mutex‐attr);
    //销毁锁
    int pthread_mutex_destroy(pthread_mutex_t *mutex);
    //上锁
    int pthread_mutex_lock(pthread_mutex_t *mutex);
    //解锁
    int pthread_mutex_unlock(pthread_mutex_t *mutex);

  1. API参数

  • pthread_mutex_t *mutex:创建的锁(互斥量),类型为pthread_mutex_t;

  • const pthread_mutexattr_t *mutex‐attr:锁的属性,当为NULL时,默认为互斥锁;

  • 返回值:都是成功返回0,错误返回-1,设置错误码。

  1. API的demo

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

pthread_mutex_t mutex;

void *fun1(void *arg){
    pthread_mutex_lock(&mutex);//上锁
    for(int i=0;i<3;i++){
        printf("task_1 : thread is create\n");
        printf("task_1 : %ld \n",(unsigned long)pthread_self());
    }
    pthread_mutex_unlock(&mutex);//解锁
}

void *fun2(void *arg){
    usleep(1);
    printf("task_2 : thread is create\n");
    printf("task_2 : %ld \n",(unsigned long)pthread_self());
}

int main()
{
    pthread_t task_1;
    pthread_t task_2;
    int ret;
    int param = 100;
   
    pthread_mutex_init(&mutex, NULL);    //创建锁

    ret = pthread_create(&task_1, NULL, fun1, (void *)&param);
    if(ret == 0){
        printf("main : task_1 create success\n");
    }
    
    ret = pthread_create(&task_2, NULL, fun2, (void *)&param);
    if(ret == 0){
        printf("main : task_2 create success\n");
    }
    printf("main : %ld\n",(unsigned long)pthread_self());
    
    pthread_join(task_1,NULL);
    pthread_join(task_2,NULL);
    pthread_mutex_destroy(&mutex);        //销毁锁
    return 0;
}

  1. demo的运行

  1. 在task_1上锁之后,会先执行完线程1里面的内容,不被打断

五、死锁

  1. 死锁是相对一个概念,就是两个线程互锁住了,僵持不下;

  1. 我们要避免出现死锁,所以在使用锁的时候要格外注意是否出现死锁;

  1. 死锁的demo

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

pthread_mutex_t mutex_1;
pthread_mutex_t mutex_2;

void *fun1(void *arg){
    pthread_mutex_lock(&mutex_1);//上锁
    sleep(1);
    pthread_mutex_lock(&mutex_2);

    for(int i=0;i<3;i++){
        printf("task_1 : thread is create\n");
        printf("task_1 : %ld \n",(unsigned long)pthread_self());
    }
    pthread_mutex_unlock(&mutex_1); //解锁
}

void *fun2(void *arg){
    pthread_mutex_lock(&mutex_2);//上锁
    sleep(1);
    pthread_mutex_lock(&mutex_1);
    for(int i=0;i<3;i++){
        printf("task_2 : thread is create\n");
        printf("task_2 : %ld \n",(unsigned long)pthread_self());
    }
    pthread_mutex_unlock(&mutex_2);//解锁
}

int main()
{
    pthread_t task_1;
    pthread_t task_2;
    int ret;
    int param = 100;

    pthread_mutex_init(&mutex_1, NULL);    //创建锁1
    pthread_mutex_init(&mutex_2, NULL);    //创建锁2

    ret = pthread_create(&task_1, NULL, fun1, (void *)&param);
    if(ret == 0){
        printf("main : task_1 create success\n");
    }
    
    ret = pthread_create(&task_2, NULL, fun2, (void *)&param);
    if(ret == 0){
        printf("main : task_2 create success\n");
    }
    printf("main : %ld\n",(unsigned long)pthread_self());
    
    pthread_join(task_1,NULL);              //等待线程1
    pthread_join(task_2,NULL);              //等待线程2
    pthread_mutex_destroy(&mutex_1);        //销毁锁1
    pthread_mutex_destroy(&mutex_2);        //销毁锁2
    return 0;
}

  1. demo的运行

  1. 如上图所示,两个线程被相互锁住,进程卡住运行不了。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

二灰酱

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

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

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

打赏作者

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

抵扣说明:

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

余额充值