引用进阶
#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, 0,customPthreadTask(), &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, 0,runTask(), &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, 0,runTask(), &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;
}