美文网首页
C++引用进阶和多线程

C++引用进阶和多线程

作者: 大虾啊啊啊 | 来源:发表于2022-08-21 11:47 被阅读0次

1、引用进阶

class Student {
private:
    string name;
public:
    void setName(string name) {
        this->name = name;
    }

    string &getName() {
        return this->name;
    }

    string getName2() {
        return this->name;
    }
};
/**
 * 引用进阶
 * @return
 */
int main() {
    Student student;
    student.setName("xiaohong");
    cout << student.getName() << endl;
    //因为返回的是引用,所以会修改值
    student.getName() = "xiaoming";
    cout << student.getName() << endl;
    //因为返回的是非引用,只是值传递,所以不会修改值
    student.getName2() = "xiaowang";
    cout << student.getName() << endl;

    return 0;
}

xiaohong
xiaoming
xiaoming

在getName函数中,如果返回的是引用,可以直接通过赋值修改。如果返回的是值,则不能修改。

2、多线程pthread

启动一个线程

pthread_join函数为等待异步线程执行完毕

/**
 * 函数指针
 * @param value
 * @return
 */
void *run(void *value) {
    //通用类型指针转成 int类型指针
    int *number = static_cast<int*>(value);
    cout<<"异步线程启动了:"<<*number<<endl;
    return 0;
}
/**
 * void * 代表通用类型
 * @return
 */
int main() {
    int number = 888;
    pthread_t pthreadId;//线程ID
    //参数1 线程id
    //参数2 线程属性 传0即可
    //参数3 函数指针
    //参数4 给函数指针传值
    pthread_create(&pthreadId, 0, run, &number);
    pthread_join(pthreadId, 0);
    cout << "main 函数弹栈了" << endl;
}

异步线程启动了:888
main 函数弹栈了

c++中的互斥锁

(1)声明一个互斥锁
pthread_mutex_mutex
(2) 初始化互斥锁
pthread_mutex_init(&mutex, NULL);
(3)销毁互斥锁
pthread_mutex_destroy(&mutex);
(4)加锁
pthread_mutex_lock(&mutex);
(5)解锁
pthread_mutex_unlock(&mutex);

#include <iostream>

#include <vector>
#include <stack>
#include <queue> // 队列支持(内部:基本上 链表 、 数组 )
#include <list> // list容器的支持
#include <set>
#include <map>
#include <algorithm> // 算法包
#include <unistd.h> // sleep(秒)

using namespace std;

pthread_mutex_t mutex;//定义一个互斥锁(ygwin平台 此互斥锁,不能有野指针)
queue<int> queues;
/**
 * 函数指针
 * @param value
 * @return
 */
void *run(void *value) {
    //加锁
    pthread_mutex_lock(&mutex);
    //通用类型指针转成 int类型指针
    int *number = static_cast<int *>(value);
    if(queues.empty()){
        cout << "异步线程:" << *number <<"没有数据,加入数据,"<<*number<< endl;
        queues.push(*number);
    }
    else{
        int value = queues.front();
        queues.pop();
        cout << "异步线程:" << *number <<"有数据,取出数据,"<<value<<"并弹出数据"<< endl;
    }

    //解锁
    pthread_mutex_unlock(&mutex);
    return 0;
}

/**
 * void * 代表通用类型
 * @return
 */
int main() {
    //初始化互斥锁
    pthread_mutex_init(&mutex, NULL);
    //定义10个线程
    pthread_t pthreadIds[10];//线程ID
    //参数1 线程id
    //参数2 线程属性 传0即可
    //参数3 函数指针
    //参数4 给函数指针传值
    //  cout<<"开始启动第:"<<i<<"个线程"<<endl;
    int number = 100;
    int number1 = 101;
    int number2 = 102;
    int number3 = 103;
    int number4 = 104;
    pthread_create(&pthreadIds[0], 0, run, &number);
    pthread_create(&pthreadIds[1], 0, run, &number1);
    pthread_create(&pthreadIds[2], 0, run, &number2);
    pthread_create(&pthreadIds[3], 0, run, &number3);
    pthread_create(&pthreadIds[4], 0, run, &number4);
    //休眠20S
    sleep(20);
    cout << "main 函数弹栈了" << endl;
    //销毁互斥锁
    pthread_mutex_destroy(&mutex);
    return 0;
}

异步线程:100没有数据,加入数据,100
异步线程:101有数据,取出数据,100并弹出数据
异步线程:102没有数据,加入数据,102
异步线程:103有数据,取出数据,102并弹出数据
异步线程:104没有数据,加入数据,104
main 函数弹栈了

互斥锁+条件变量+等待唤醒+队列实现生产者消费者模式

//
// Created by DELL on 2022/9/6.
//

#ifndef JNI_05_VIDEOCHANNEL_H
#define JNI_05_VIDEOCHANNEL_H

#include <queue>
#include <pthread.h>
#include <android/log.h>
#include "SafeQueue.h"

using namespace std;
#define TAG "MainActivity_C"
// ... 我都不知道传入什么  借助JNI里面的宏来自动帮我填充
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, TAG, __VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, TAG, __VA_ARGS__)
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, TAG, __VA_ARGS__)

class VideoChannel {
private:


public:
    VideoChannel();

    /**
     * 插入数据
     */
    void insert();

    /**
     * 取出数据,并删除
     */
    void getAndDelete();

    /**
     * 队列
     */
    SafeQueue<int> queues;

    /**
     * 开启生产、消费者模式
     */
    void start();
};


#endif //JNI_05_VIDEOCHANNEL_H

//
// Created by DELL on 2022/9/6.
//

#include "VideoChannel.h"

VideoChannel::VideoChannel() {
}


void *add(void *object) {
    VideoChannel *channel = static_cast<VideoChannel *>(object);
    channel->insert();
    return nullptr;
}

void *get(void *object) {
    VideoChannel *channel = static_cast<VideoChannel *>(object);
    channel->getAndDelete();
    return nullptr;
}

/**
 * 添加
 */
void VideoChannel::insert() {
    while (true) {
        queues.insert(1);
        LOGD("插入的值是%d", 1);
    }
}
/**
 * 取出
 */
void VideoChannel::getAndDelete() {
    while (true) {
        int value = 0;
        queues.getAndDelete(value);
        LOGD("取出的值是%d", value);
    }


}
/**
 * 开启
 */
void VideoChannel::start() {
    pthread_t pid;
    pthread_t pid2;
    //
    pthread_create(&pid, nullptr, get, this);
    pthread_create(&pid2, nullptr, add, this);
}

//
// Created by DELL on 2022/9/7.
//

#ifndef JNI_05_SAFEQUEUE_H
#define JNI_05_SAFEQUEUE_H

#include <queue>
#include <pthread.h>
#include <android/log.h>
#include <unistd.h>

using namespace std;
#define TAG "MainActivity_C"
// ... 我都不知道传入什么  借助JNI里面的宏来自动帮我填充
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, TAG, __VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, TAG, __VA_ARGS__)
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, TAG, __VA_ARGS__)

template<typename T>
class SafeQueue {

private:
    queue<T> queue;
    pthread_mutex_t mutex;//定义一个互斥锁
    pthread_cond_t cond;//条件变量

public:
    SafeQueue() {
        //初始化互斥锁
        pthread_mutex_init(&mutex, NULL);
        // 初始化 条件变量
        pthread_cond_init(&cond, 0);
    }

    /**
     * 插入数据
     * @param t
     */
    void insert(T t) {
        //插入数据的时候先锁住
        pthread_mutex_lock(&mutex);
        if (!queue.empty()) {
            //等待
            pthread_cond_wait(&cond, &mutex);
        }
        queue.push(t);
        sleep(1);
        //唤醒
        pthread_cond_signal(&cond);
        //解锁
        pthread_mutex_unlock(&mutex);

    }

    /**
     * 取出数据
     * @param t
     * @return
     */
    void getAndDelete(T &t) {
        //取出数据的时候先锁住
        pthread_mutex_lock(&mutex);
        if (queue.empty()) {
            //等待
            pthread_cond_wait(&cond, &mutex);
        }
        //取出数据
        t = queue.front();
        //把这条数据弹出去
        queue.pop();
        sleep(1);
        //唤醒
        pthread_cond_signal(&cond);
        //解锁
        pthread_mutex_unlock(&mutex);


    }
};


#endif //JNI_05_SAFEQUEUE_H

2022-09-07 16:12:48.153 26935-27192/com.hvm.vender.jni_05 D/MainActivity_C: 插入的值是1
2022-09-07 16:12:49.154 26935-27191/com.hvm.vender.jni_05 D/MainActivity_C: 取出的值是1
2022-09-07 16:12:50.154 26935-27192/com.hvm.vender.jni_05 D/MainActivity_C: 插入的值是1
2022-09-07 16:12:51.154 26935-27191/com.hvm.vender.jni_05 D/MainActivity_C: 取出的值是1
2022-09-07 16:12:52.155 26935-27192/com.hvm.vender.jni_05 D/MainActivity_C: 插入的值是1
2022-09-07 16:12:53.155 26935-27191/com.hvm.vender.jni_05 D/MainActivity_C: 取出的值是1
2022-09-07 16:12:54.155 26935-27192/com.hvm.vender.jni_05 D/MainActivity_C: 插入的值是1
2022-09-07 16:12:55.156 26935-27191/com.hvm.vender.jni_05 D/MainActivity_C: 取出的值是1

结果得知调用pthread_cond_wait等待的时候,会释放当前锁,调用pthread_cond_signal唤醒不会释放当前锁。需要手动释放锁

相关文章

  • C++引用进阶和多线程

    1、引用进阶 在getName函数中,如果返回的是引用,可以直接通过赋值修改。如果返回的是值,则不能修改。 2、多...

  • C++使用Lambda函数实现多线程

    转帖: C++使用Lambda函数实现多线程thread - 传递引用参数

  • C++基础

    C++ 值传递、指针传递、引用传递详解C++中引用传递与指针传递区别 引用传递和指针传递的区别 引用的规则:(1)...

  • C++入门系列博客三 引用和指针

    C++ 引用和指针 作者:AceTan,转载请标明出处! 引用和指针对于C++来说很重要,是学习C++绕不过去的一...

  • C++ 引用传递的学习

    C++ 引用与引用作为函数的参数C++函数的三种传递方式为:值传递、指针传递和引用传递 C++ 上课习题 刘月林2...

  • C++ 多线程

    C++ 多线程 | 菜鸟教程 C++ 11 多线程--线程管理 - Brook_icv - 博客园

  • 函数的进阶

    第11天 今天学习函数进阶 一、绝对引用和相对引用: 相对引用: 引用的地址不是固定的 绝对引用: 引用的...

  • C/C++ basis 01

    1. C和C++区别 2. 指针和引用 sizeof(引用)等于 引用指向对象的大小。 对比值传递,引用传递(引用...

  • 第十四周笔记分享

    Android开发高级进阶 一、多线程 二、new Thread()和ThreadPoolExceutor的区别:...

  • Swift多线程:GCD进阶,单例、信号量、任务组

    Swift多线程:GCD进阶,单例、信号量、任务组 Swift多线程:GCD进阶,单例、信号量、任务组

网友评论

      本文标题:C++引用进阶和多线程

      本文链接:https://www.haomeiwen.com/subject/gusvgrtx.html