IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 系统运维 -> Linux 多线程编程 -> 正文阅读

[系统运维]Linux 多线程编程

Linux 多线程的概念

1.线程的创建

#include <pthread.h>
int pthread_create(pthread_t *restrict tidp, const pthread_attr_t *restrict attr, void *(*start_rtn)(void *), void *restrict arg);
// 返回:若成功返回0,否则返回错误编号
//pthread_t *restrict tidp:长整型的指针,当pthread_create成功返回时,由tidp指向的内存单元被设置为新创建线程的线程ID。
//const pthread_attr_t *restrict attr:线程的属性,attr参数用于定制各种不同的线程属性,暂可以把它设置为NULL,以创建默认属性的线程。
//void *(*start_rtn)(void *):函数指针,新创建的线程从start_rtn函数的地址开始运行,该函数只有一个无类型指针参数arg。
//void *restrict arg:传参的参数,如果需要向start_rtn函数传递的参数不止一个,那么需要把这些参数放到一个结构中,然后把这个结构的地址作为arg参数传入。

2.线程的退出

#include <pthread.h>
int pthread_exit(void *rval_ptr);
//rval_ptr是一个无类型指针,与传给启动例程的单个参数类似。进程中的其他线程可以通过调用pthread_join函数访问到这个指针。

3.线程的等待

#include <pthread.h>
int pthread_join(pthread_t thread, void **rval_ptr);//可回收pthread_exit的返回值
// 返回:若成功返回0,否则返回错误编号
//调用这个函数的线程将一直阻塞,直到指定的线程调用pthread_exit、从启动例程中返回或者被取消。

4.线程ID获取

#include <pthread.h>
pthread_t pthread_self(void);
// 返回:调用线程的ID(unsigned long)长整型

函数应用

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

//int pthread_create(pthread_t *restrict tidp, const pthread_attr_t *restrict attr, void *(*start_rtn)(void *), void *restrict arg);


void *func1(void *arg)
{
        //static int ret = 10;
        static char *p = "t1 run out\n";//二级指针指向p,使用static可保证平的数值不改变 

        printf("t1:%ld,this is create\n",(unsigned long)pthread_self());
        printf("t1:parm is:%d\n",*(int *)arg);
        pthread_exit((void *)p);

}


int main()
{
        int ret;
        pthread_t t1;
        int parm = 100;
        char *pret;

        ret = pthread_create(&t1, NULL, func1, (void *)&parm);//线程的创建

        printf("main:%ld\n",(unsigned long)pthread_self());
        //int pthread_join(pthread_t thread, void **rval_ptr);
        pthread_join(t1, (void **)&pret);//等待新线程的退出
        printf("main:t1 quit:%s\n",pret);//获取退出的返回值
        return 0;
}


在这里插入图片描述

验证共享内存

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

//int pthread_create(pthread_t *restrict tidp, const pthread_attr_t *restrict attr, void *(*start_rtn)(void *), void *restrict arg);
int data = 0;

void *func1(void *arg)
{
        //static int ret = 10;
        static char *p = "t1 run out\n";

        printf("t1:%ld,this is create\n",(unsigned long)pthread_self());
        printf("t1:parm is:%d\n",*(int *)arg);

        while(1){
                printf("t1:data = %d\n",data++);
                sleep(1);
        }
        pthread_exit((void *)p);
}


void *func2(void *arg)
{
        //static int ret = 10;
        static char *p = "t2 run out\n";

        printf("t2:%ld,this is create\n",(unsigned long)pthread_self());
        printf("t2:parm is:%d\n",*(int *)arg);

        while(1){
                printf("t2:data = %d\n",data++);
                sleep(1);
        }
        pthread_exit((void *)p);
}

int main()
{
        int ret;
        int ret2;
        pthread_t t1;
		pthread_t t2;
        int parm = 100;
        char *pret;

        ret = pthread_create(&t1, NULL, func1, (void *)&parm);
        ret2 = pthread_create(&t2, NULL, func2, (void *)&parm);

        printf("main:%ld\n",(unsigned long)pthread_self());

        while(1){
                printf("main:data = %d\n",data++);
                sleep(1);
        }
        //int pthread_join(pthread_t thread, void **rval_ptr);
        pthread_join(t1, (void **)&pret);
        printf("main:t1 quit:%s\n",pret);
        return 0;
}

在这里插入图片描述

5.创建锁

#include <pthread.h>
pthread_mutex_t mutex; //定义一个全局变量的锁
int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr);// 返回:若成功返回0,否则返回错误编号
//pthread_mutex_t *restrict mutex:(&mntex)指针
//const pthread_mutexattr_t *restrict attr://锁的属性,要用默认的属性初始化互斥量,只需把attr设置为NULL

6.销毁锁

#include <pthread.h>
int pthread_mutex_destroy(pthread_mutex_t *mutex);
// 返回:若成功返回0,否则返回错误编号

7.加锁

#include <pthread.h>
int pthread_mutex_lock(pthread_mutex_t *mutex);
int pthread_mutex_trylock(pthread_mutex_t *mutex);
// 返回:若成功返回0,否则返回错误编号

8.解锁

int pthread_mutex_unlock(pthread_mutex_t *mutex);
// 返回:若成功返回0,否则返回错误编号

9.函数应用

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

//int pthread_create(pthread_t *restrict tidp, const pthread_attr_t *restrict attr, void *(*start_rtn)(void *), void *restrict arg);


pthread_mutex_t mutex;//定义一个全局变量的锁


void *func1(void *arg)
{
        int i;
        pthread_mutex_lock(&mutex);//加锁
        for(i=0;i<5;i++){
                printf("t1:%ld,this is create\n",(unsigned long)pthread_self());
                printf("t1:parm is:%d\n",*(int *)arg);
                sleep(1);
        }
        pthread_mutex_unlock(&mutex);//解锁
        pthread_exit(NULL);//退出线程
}


void *func2(void *arg)
{
        pthread_mutex_lock(&mutex);
        printf("t2:%ld,this is create2\n",(unsigned long)pthread_self());
        printf("t2:parm is:%d\n",*(int *)arg);
        pthread_mutex_unlock(&mutex);
        pthread_exit(NULL);
}

int main()
{
        int ret;
        pthread_t t1;
        pthread_t t2;
        int parm = 100;

        //int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr);
        pthread_mutex_init(&mutex, NULL);//创建锁
        ret = pthread_create(&t1, NULL, func1, (void *)&parm);
        ret = pthread_create(&t2, NULL, func2, (void *)&parm);



        printf("main:%ld\n",(unsigned long)pthread_self());

        pthread_join(t1, NULL);//等待t1线程
        pthread_join(t2, NULL);

        pthread_mutex_destroy(&mutex);//销毁锁

        return 0;
}

在这里插入图片描述

10.互斥锁(实现t1获取到3)

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

//int pthread_create(pthread_t *restrict tidp, const pthread_attr_t *restrict attr, void *(*start_rtn)(void *), void *restrict arg);


pthread_mutex_t mutex;
int data = 0;

void *func1(void *arg)
{
        pthread_mutex_lock(&mutex);
        while(1){
                printf("t1:%ld,this is create\n",(unsigned long)pthread_self());
                printf("t1:parm is:%d\n",*(int *)arg);
                printf("t1 data = %d\n",data++);
                sleep(1);
                if(data == 3){
                        pthread_mutex_unlock(&mutex);
                        pthread_exit(NULL);

                }
        }
}


void *func2(void *arg)
{
        while(1){
                pthread_mutex_lock(&mutex);
                printf("t2:%ld,this is create2\n",(unsigned long)pthread_self());
                printf("t2:parm is:%d\n",*(int *)arg);
                printf("t2 data = %d\n",data);
                pthread_mutex_unlock(&mutex);
                sleep(1);
        }
        pthread_exit(NULL);
}

int main()
{
        int ret;
        pthread_t t1;
        pthread_t t2;
        int parm = 100;

        //int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr);
        pthread_mutex_init(&mutex, NULL);
        ret = pthread_create(&t1, NULL, func1, (void *)&parm);
        ret = pthread_create(&t2, NULL, func2, (void *)&parm);



        printf("main:%ld\n",(unsigned long)pthread_self());

        pthread_join(t1, NULL);
        pthread_join(t2, NULL);

        pthread_mutex_destroy(&mutex);

        return 0;
}




这样可以实现,不管是t1还是t2线程先拿到锁,t1线程都可以遍历到3再解锁。

11.死锁

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

//int pthread_create(pthread_t *restrict tidp, const pthread_attr_t *restrict attr, void *(*start_rtn)(void *), void *restrict arg);


pthread_mutex_t mutex;
pthread_mutex_t mutex2;


void *func1(void *arg)
{
        int i;
        pthread_mutex_lock(&mutex);//获取了锁1,想要获取锁2,但锁2被线程t2获取了,相互竞争,形成死锁。
        sleep(1);
        pthread_mutex_lock(&mutex2);
        for(i=0;i<5;i++){
                printf("t1:%ld,this is create\n",(unsigned long)pthread_self());
                printf("t1:parm is:%d\n",*(int *)arg);
                sleep(1);
        }
        pthread_mutex_unlock(&mutex);
        pthread_exit(NULL);
}


void *func2(void *arg)
{
        pthread_mutex_lock(&mutex2);//获取了锁2,想要获取锁1,但锁1被线程t1获取了,相互竞争,形成死锁。
        sleep(1);
        pthread_mutex_lock(&mutex);
        printf("t2:%ld,this is create2\n",(unsigned long)pthread_self());
        printf("t2:parm is:%d\n",*(int *)arg);
        pthread_mutex_unlock(&mutex);
        pthread_exit(NULL);
}

int main()
{
        int ret;
        pthread_t t1;
        pthread_t t2;
        int parm = 100;

        //int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr);
        pthread_mutex_init(&mutex, NULL);
        pthread_mutex_init(&mutex2, NULL);


        ret = pthread_create(&t1, NULL, func1, (void *)&parm);
        ret = pthread_create(&t2, NULL, func2, (void *)&parm);



        printf("main:%ld\n",(unsigned long)pthread_self());

        pthread_join(t1, NULL);
        pthread_join(t2, NULL);

        pthread_mutex_destroy(&mutex);

        return 0;
}

在这里插入图片描述
有两个锁时,当线程1获取到一把锁时,想要获取另一把锁,但是另一把锁被线程2获取,同时线程2想要获取线程1获取的锁,两个线程相互竞争对方获取的锁,从而形成死锁。

12.条件

  1. 创建
pthread_cond_t cond;
int pthread_cond_init(pthread_cond_t *restrict cond, const pthread_condattr_t *restrict attr);
//pthread_cont_init函数的attr参数可以设置为NULL

2.销毁

int pthread_cond_destroy(pthread_cond_t *cond);

3.等待

int pthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex);

int pthread_cond_timedwait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex, cond struct timespec *restrict timeout);
//timeout指定了等待的时间,它是通过timespec结构指定

4.触发

int pthread_cond_signal(pthread_cond_t *cond);
//pthread_cond_signal函数将唤醒等待该条件的某个线程

5.广播

int pthread_cond_broadcast(pthread_cond_t *cond);
//pthread_cond_broadcast函数将唤醒等待该条件的所有进程

13.条件示例

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

//int pthread_create(pthread_t *restrict tidp, const pthread_attr_t *restrict attr, void *(*start_rtn)(void *), void *restrict arg);


pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;//静态初始化
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
int data = 0;

void *func1(void *arg)
{
        while(1){
                pthread_cond_wait(&cond, &mutex);//等待触发条件
                printf("t1:%ld,this is create\n",(unsigned long)pthread_self());
                printf("t1:parm is:%d\n",*(int *)arg);
                printf("t1 data = %d=====================\n",data);
                data = 0;
                sleep(1);
        }

}


void *func2(void *arg)
{
        while(1){
                pthread_mutex_lock(&mutex);
                printf("t2:%ld,this is create2\n",(unsigned long)pthread_self());
                printf("t2:parm is:%d\n",*(int *)arg);
                printf("t2 data = %d\n",data++);
                if(data == 3){
                         pthread_cond_signal(&cond);//触发
                }
                pthread_mutex_unlock(&mutex);
                sleep(1);
        }
        pthread_exit(NULL);
}

int main()
{
        int ret;
        pthread_t t1;
        pthread_t t2;
        int parm = 100;

        //int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr);
       //pthread_mutex_init(&mutex, NULL);
       //pthread_cond_init(&cond, NULL);//创建条件

        ret = pthread_create(&t1, NULL, func1, (void *)&parm);
        ret = pthread_create(&t2, NULL, func2, (void *)&parm);



        printf("main:%ld\n",(unsigned long)pthread_self());

        pthread_join(t1, NULL);
        pthread_join(t2, NULL);

        pthread_mutex_destroy(&mutex);
        pthread_cond_destroy(&cond);
        return 0;
}

在这里插入图片描述

14.程序测试流程

1.创建测试文件

int main(int argc,char **argv)
{
        int time = atoi(argv[1]);
        int i;
        for(i = 0;i < time;i++){
                system("./test");//要跑的程序
        }
}
  1. 编辑它
  2. ./a.out 10 >>test.txt & //把要跑的程序,跑10次,存放到test.txt文件中
  3. 查阅test.txt文件,查看结果 。

15.生产者与消费者的问题

生产者与消费者的问题

  系统运维 最新文章
配置小型公司网络WLAN基本业务(AC通过三层
如何在交付运维过程中建立风险底线意识,提
快速传输大文件,怎么通过网络传大文件给对
从游戏服务端角度分析移动同步(状态同步)
MySQL使用MyCat实现分库分表
如何用DWDM射频光纤技术实现200公里外的站点
国内顺畅下载k8s.gcr.io的镜像
自动化测试appium
ctfshow ssrf
Linux操作系统学习之实用指令(Centos7/8均
上一篇文章           查看所有文章
加:2022-03-04 16:00:29  更:2022-03-04 16:04:46 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/16 3:37:04-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码