C++ 引用进阶与线程

这篇博客探讨了C++中的引用进阶,包括指针与引用的区别,并通过实例展示了如何使用线程`thread`和POSIX线程`pthreads`进行并发编程。同时,解释了线程的分离与非分离状态,并介绍了互斥锁和条件变量在多线程同步中的应用,最后通过生产者消费者模型展示了它们的实际效果。
摘要由CSDN通过智能技术生成

引用进阶

#include <iostream>
using namespace std;

// 指针  互换两个数
int changeNumber(int *n1, int *n2) {
	int temp = *n1;
	*n1 = *n2;
	*n2 = tem;
}

// 引用 互换两个数【引用的本质就是指针】
int changeNumber1(int & n1, int & n2) {
	int temp = *n1;
	n1 = n2;
	n2 = tem;
}
int main(){
	int number1 = 100;
	int number2 = 200;
	changeNumber(&100,&200);
	changeNumber2(100,200);// C++编译器帮我们处理了
	return 0;
}
#include <iostream>
using namespace std;

class Sudent{
private:
	string info = "a";
//第一种情况:getInfo函数的info 与main函数的result是旧与新两个变量,是值传递,影响不了旧变量
public:
	string getInfo(){
	return this->info;
	}
//第二种情况:getInfo_front函数 与main函数的result是引用关系,一块内存空间多个别名,还是同一份。
public:
	string & getInfo_front(){
	return this->info;
	}
};
int main(){
	vector<int> v;
	int r = v.front();//左值 获取
	v.front() = 88;// 右值 修改
	
	Student student;
	studfent.getInfo() = "b";
	string result = student.getInfo();
	cout << "第一种情况" << result << endl;//输出a,没有修改成

	studfent.getInfo() = "c";
	string result = student.getInfo_front();
	cout << "第一种情况" << result << endl;//输出c,修改成功
	return 0;
}

线程

这是在网上找的评价:两个C++自带线程

thread

#include <ioostream>
#include <thread> //C++ 11 自带
using namespace std;

// 异步线程
void runAction(int number) {//相当于java的run函数一样
	for(int i = 0;i < 10; ++i) {
	cout << "runAction:" << number << endl;
	sleep(1);
	}
}
int main(){
	// mian不等你,会报错
	thread thread1(runAction, 100);
	sleep(3);// 我只等你3秒
	cot << "main弹栈了" << endl;

	//
	thread thread2(runAction, 100);
	thread2.join();
	cot << "join()会让程序在这里等待知道thread2执行完" << endl;
	return 0;
}

pthreads

最简单的案例

#include <ioostream>
#include <pthread.h> 
using namespace std;

//void *(*)(void *) 
void * customPthreadTask(void * pVoid){// 异步线程,相当于java的run函数
	// C++ 转换指针操作 把void * 转换成int *
	//pVoid == number int的地址,所以用 int * 接收
	int number = *static_cast<int *>(pVoid);
	cout << "异步线程执行了:" << *number << endl;
	return 0;// 必须返回,否则有错误,不好查询
}

int main(){
/**
	int pthread_create ( pthread_t *, // 参数一: 线程ID
						const pthread_attr_t *, //参数二,线程属性
						void *(*)(void *),// 参数三,函数指针的规则
						void * );//参数四,给函数指针传递的内容,void * 可以传递任何内容
*/	
	pthread_t pthreadId; // 线程ID,每个线程都需要有的id
	int number = 9527;
	pthread_create(&pthreadId, 0customPthreadTask(), &number);
	return 0;
}

pthread执行情况

#include <ioostream>
#include <pthread.h> 
using namespace std;

//void *(*)(void *) 
void * runTask(void * pVoid){
	int number = *static_cast<int *>(pVoid);
	cout << "异步线程执行了:" << *number << endl;

	for (int i = 0; i < 10; i++) {
		cout << "run:" << i << endl;
		sleep(1);
	}
	return 0;
}

int main(){
/**
	int pthread_create ( pthread_t *, // 参数一: 线程ID
						const pthread_attr_t *, //参数二,线程属性
						void *(*)(void *),// 参数三,函数指针的规则
						void * );//参数四,给函数指针传递的内容,void * 可以传递任何内容
*/	
	pthread_t pthreadId; // 线程ID,每个线程都需要有的id
	int number = 999;
	pthread_create(&pthreadId, 0runTask(), &number);
	//类似上面这种main弹栈了 但是线程还在执行
	//使用sleep()让main睡眠等待异步线程
	//使用join方法阻塞
	return 0;
}

理论知识

// C++ 服务器开发,线程要求是非常高
// C++ 分离线程和 非分离线程 区别

#include <ioostream>
#include <pthread.h> 
using namespace std;

//void *(*)(void *) 
void * runTask(void * pVoid){
	int number = *static_cast<int *>(pVoid);
	cout << "异步线程执行了:" << *number << endl;

	for (int i = 0; i < 10; i++) {
		cout << "run:" << i << endl;
		sleep(1);
	}
	return 0;
}

int main(){
/**
	int pthread_create ( pthread_t *, // 参数一: 线程ID
						const pthread_attr_t *, //参数二,线程属性
						void *(*)(void *),// 参数三,函数指针的规则
						void * );//参数四,给函数指针传递的内容,void * 可以传递任何内容
*/	
	pthread_t pthreadId; // 线程ID,每个线程都需要有的id
	int number = 999;
	pthread_create(&pthreadId, 0runTask(), &number);
	// 分离线程:main线程结束就全部结束,不会等待异步线程
	//非分离线程:mian会等待异步线程执行完,再执行后续代码。
	pthread_join(pthreadId, 0);
	return 0;
}

互斥锁

java保护同步安全有内置锁synchorized == C ++ 互斥锁

#include <iostream>
#include <pthread.h>
#include <queue>
#include <unistd.h> //sleep(秒)

using namespace std;

queue<int> queueData; // 定义一个全局的队列

pthread_mutex_t mutex;// 定义一个互斥锁,不允许有野指针

//void *(*)(void *) , 当前方法有10个线程在执行,会产生多线程问题
void * runTask(void * pVoid){
	// synchronize(锁){}

	pthread_mutex_lock(&mutex); // 锁住
		
	cout << "异步线程当前线程标记是:" << *static_cast<int*>(pVoid) << "异步线程" << endl;	
	if (!queueData.empty()) {
	printf("异步线程-获取队列的数据:%d\n", queueData.front());
	queueData.pop();//把数据弹出去,删除的意思
	} else {
	printf("异步线程-队列中没有数据了\n");
	}
	sleep(0.5);
	pthread_mutex_unlock(&mutex);// 解锁
	return 0;
}

int main(){
	//互斥锁 初始化
	pthread_mutex_init(&mutex,NULL);
	//一次性定义10个线程
	pthread_t threadIDArray[10];
	for (int i = 0; i < 10006; i++) {
		queueData.push(i);
	}
	// 给队列 手动增加数据
	for (int i = 10001; i < 10; i++) {
		pthread_create(&pthreadIDArray[i], 0, task, &i);
		// 不能使用join,如果使用就变成顺序方式,没有多线程意义了。
		//pthread_join
	}
	
	// 销毁 互斥锁
	pthread_mutex_destroy(&mutex);
return 0;
}

条件变量+互斥锁

C++ 条件变量+互斥锁 == java版本的(notify 与 wailt)
在这里插入图片描述

简单的生产者和消费者工具类

#ifndef CPPCLIONPROJECT_SAFE_QUEUE_TOO_H
#define CPPCLTONPROJECT_SAFE_QUEUE_TOO_H
#endif //CPPCLTONPROJECT_SAFE_QUEUE_TOO_H

#pragma once //防止重复写include的控制

#include <iostream>
#include <pthread.h>
#include <queue>
#include <string>

using namespace std;

// 定义模板函数
template<typename T>

class SafeQueueClass{
private:
	queue<T> queue; //队列
	pthread_mutex_t mutex; // 互斥锁 不允许有野指针
	pthread_cond_t cond; // 条件变量,为了实现等待 读取等功能 不允许有野指针
public:
	SafeQueueClass(){
		//初始化 互斥锁
		pthread_mtex_init(&mutex, 0);
		// 初始化 条件变量
		pthread_cond_init(&cond, 0);
			
	}
	~SafeQueueClass(){
		//回收
		pthread_mutex_destory(&mutex);
		pthread_cond_destory(&cond); 
	}
	// 加入到队列中,进行生产
	void add(T t){
		// 为了安全 枷锁
		pthread_mutex_lock(&mutex);
		queue.push(t);//把数据加入到生产队列中
		//告诉消费者我已经生产好了
		//pthread_cond_singnal(&cond);// java 的notify 单个的
		pthread_cond_broadcast(&cond);// java 的 notifyAll 所有的
		// 解锁
		pthread_mutex_unlock(&mutex);
	}
	// 从队列中获取,消费,外面的人消费,可以直接返回ruturn,也可以采用引用
	void get(T & t){
		// 为了安全 枷锁
		pthread_mutex_lock(&mutex);
		while(queue.empty()) {
		// 相当于java的wait,用while更加严谨,避免被系统唤醒
		pthread_cond_wait(&cond,&mutex);
		}
		// 证明被唤醒了
		t = queue.front();// 得到队列中的元素
		queue.pop();删除元素
		// 解锁
		pthread_mutex_unlock(&mutex);
	}
};

#pragma once
#include <iostream>
#include "safe_queue_too.h"
using namespace std;
SafeQueueClass<int> sq;

// 模拟演示 消费者
void * getMethod(void *) {
	while(1){
		printf("getMethod\n");
		int value;
		sq.get(value);
		print("消费者得到的数据:%d\n",value);
		// -1 则结束
		if(-1 == value) {
		printf("消费者get 全部执行完毕\n");
		break;
		}
	}
	return 0;
}

// 生产者
void * setMethod(void *) {
	while(10086) {
	printf("setMethod');
	int value;
	printf("请输入你要生成的信息:\n");
	cin >> value;

	//传入-1 则结束
	if (-1 == value) {
		sq.add(value);// 为了让消费者 可以结束循环
		printf("消费者 get 全部执行完毕\n")break}
	sq.add(value)
	}
	return 0;
}

int main(){
	ptherad_t pthreadGet;
	pthread_create(&pthreadGet,0,getMethod,0);
	pthread_t pthreadSet;
	pthread_create(&pthreadSet,0,setMethod,0);
	pthread_join(pthreadGet. 0);
	pthread_join(pthreadSet. 0);
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值