结构体
结构体里所有的成员,都是public的
// TODO xia chen hui 2020/5/21 21:58 结构体
struct Student {
// xia chen hui 2020/5/21 21:59 里面所有的成员,都是public
char *name;
int age;
char sex;
};
共用体
在内存中只存在一个值
// TODO xia chen hui 2020/5/21 22:18 共用体
union MyCount {
int countValue1;
int countValue2;
int countValue3;
int countValue4;
int countValue5;
int countValue6;
int countValue7;
};
// TODO xia chen hui 2020/5/21 22:20 共用体
union MyCount myCount;
myCount.countValue1 = 10;
printf("myCount的值%d\n", myCount.countValue1); //输出10
myCount.countValue2 = 20;
printf("myCount的值%d\n", myCount.countValue1);//输出20,countValue1的值被改了
分离线程和非分离线程
分离线程:线程之间自己管自己,不管其他的,所以不管线程是否执行完毕,该结束就结束。
非分离线程:先执行异步任务,要等到耗时任务完成之后,才会执行join后面的关联代码
- 线程是有步骤
CmakeLists中
# 第一步,引入线程库的所有头文件
include_directories("C:/Users/Administrator/Desktop/pthreads-w32-2-9-1-release/Pre-built.2/include")
# 第二步,引入线程库的库文件,链接到库
link_directories("C:/Users/Administrator/Desktop/pthreads-w32-2-9-1-release/Pre-built.2/lib/x64")
# 第三步,链接到目标库
target_link_libraries(ndk03_code_cpp pthreadVC2)
#第五步,解决宏没有定义的问题,但是第二步选择64位的时候,好像不需要这一步
# cxx代表C++,
# "${CMAKE_CXX_FLAGS}" CMAKE_CXX_FLAGS =AAA/BB/CC.... 表示不破坏他的配置,在他的配置基础上增加
# -DHAVE_STRUCT_TIMESPEC代表增加HAVE_STRUCT_TIMESPEC这个宏,和D之间不能有空格
#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DHAVE_STRUCT_TIMESPEC")
#第四步在cpp文件中是导入头文件
#第六步,需要把C:\Users\Administrator\Desktop\pthreads-w32-2-9-1-release\Pre-built.2\dll 里的动态链接库pthreadVC2.dll交叉复制到C:\Windows的system32 和SysWOW64中。32复制到64 ,64复制到32
- 线程普通用法
//定义函数指针规则
void *customPthreadMethod(void *pVoid) {
//void *代表能接受所有类型
// static_cast<int *>(pVoid)代表把空指针转换为int类型的指针,然后加上*取出内存地址对应的值
int result = *static_cast<int *>(pVoid);
printf("耗时任务被执行...%d\n", result);
for (int i = 0; i < 50; ++i) {
Sleep(200);
printf("customPthreadMethod: i=%d\n", (i + 1));
}
//如果不返回,就会出现问题
return 0;
}
//最简单有用法
void simpleThreadTest() {
cout << "124" << endl;
pthread_t pthreadID;//线程ID
// xia chen hui 2020/5/28 0:11 参数1.线程id 2.线程属性 3.函数指针,执行异步任务,类似java的run 4.函数指针的参数传递
int value01 = 4512;
//会把value01传给customPthreadMethod
pthread_create(&pthreadID, 0, customPthreadMethod, &value01);
//pthread_join会等待耗时任务执行完成之后,才会执行后面的代码
pthread_join(pthreadID, 0);
printf("线程执行完毕...");
}
- 线程升级用
//线程升级用法
void *customPthreadMethod2(void *pVoid) {
float result = *static_cast<float *>(pVoid);
printf("2耗时任务被执行...%f\n", result);
for (int i = 0; i < 50; ++i) {
Sleep(100);
printf("customPthreadMethod2: i=%d\n", (i + 1));
}
return 0;
}
void customThreadTest() {
pthread_t pthreadID;//允许有野指针
pthread_attr_t pthreadAttr; //线程属性,不允许有野指针
//需要初始化线程属性,需要指针类型,所以传内存地址
pthread_attr_init(&pthreadAttr);
// TODO xia chen hui 2020/5/28 23:38 分离线程 和 非分离线程
// xia chen hui 2020/5/28 23:38 非分离线程:先执行异步任务,要等到耗时任务完成之后,才会执行join后面的关联代码
// xia chen hui 2020/5/28 23:38 分离线程:线程之间自己管自己,不管其他的,所以不管线程是否执行完毕,该结束就结束。
//开启分离线程。pthread_join会失效
//pthread_attr_setdetachstate(&pthreadAttr, PTHREAD_CREATE_DETACHED);
//开启非分离线程和pthread_join相关联
pthread_attr_setdetachstate(&pthreadAttr, PTHREAD_CREATE_JOINABLE);
float value = 12.3;
pthread_create(&pthreadID, &pthreadAttr, customPthreadMethod2, &value);
//耗时任务完成之后再执行 ,join第二个参数是线程执行完成后的返回结果
pthread_join(pthreadID, 0);
printf("customThreadTest线程完成之后...\n");
//完成之后回收
pthread_attr_destroy(&pthreadAttr);
}
- 线程互斥锁
// TODO xia chen hui 2020/5/28 23:51 线程的升级, 线程安全问题 互斥锁
#include <iostream>
#include <pthread.h>
#include <string>
#include <queue>
using namespace std;
//定义全局的队列
queue<int> saveAllData;
//定义一个互斥锁,不允许野指针
pthread_mutex_t mutex;
void *customThreadMethod(void *pVoid) {
// 10个线程,同时对队列的数据进行操作,并保证数据安全,(加锁)
//加锁
pthread_mutex_lock(&mutex);
printf("当前线程标记是-----------%d\n", *static_cast<int *>(pVoid));
if (!saveAllData.empty()) {
printf("获取队列的数据:%d\n", saveAllData.front());
//把数据弹出去(删除)
saveAllData.pop();
} else {
printf("队列中没有数据了...");
}
//解锁,为了让其他线程可以进来操作
pthread_mutex_unlock(&mutex);
return 0;
}
int main() {
//初始化互斥锁
pthread_mutex_init(&mutex, NULL);
//给队列初始化数据
for (int j = 1000; j < 1030; ++j) {
saveAllData.push(j);
}
//初始化线程id
pthread_t pthreadIDArray[30];
for (int i = 0; i < 30; ++i) {
//for循环开启线程
pthread_create(&pthreadIDArray[i], 0, customThreadMethod, &i);
}
//回收互斥锁
pthread_mutex_destroy(&mutex);
printf("main函数已经结束...");
//阻塞main ,为了让多线程执行完成
system("pause");
return 0;
}
- 生产者 消费者
// TODO xia chen hui 2020/5/29 20:29 生产者 消费者 工具类
#ifndef NDK03_CODE_CPP_SAFE_QUEUE_TOOL_H
#define NDK03_CODE_CPP_SAFE_QUEUE_TOOL_H
#endif //NDK03_CODE_CPP_SAFE_QUEUE_TOOL_H
#include <iostream>
#include <string>
#include <pthread.h>
#include <queue>
using namespace std;
//定义一个模板
template<typename T>
class SafeQueueClass {
private:
//定义一个队列
queue<T> queue;
//定义互斥锁,为了线程安全处理 ,不允许有野指针
pthread_mutex_t mutex;
//定义条件变量,为了实现等待读取功能 ,不允许有野指针
pthread_cond_t cond;
public:
//构造函数
SafeQueueClass() {
//初始化互斥锁
pthread_mutex_init(&mutex, NULL);
//初始化条件变量
pthread_cond_init(&cond, NULL);
}
~SafeQueueClass() {
//回收互斥锁
pthread_mutex_destroy(&mutex);
//回收条件变量
pthread_cond_destroy(&cond);
}
// TODO xia chen hui 2020/5/29 20:49 加入队列中(进行生产)
void add(T t) {
//为了保证同步的安全性,所以锁定
pthread_mutex_lock(&mutex);
queue.push(t);
//这里需要唤醒消费者,否则消费者会一直等待,
//pthread_cond_signal(&cond); //系统去唤醒一个线程,--java notify
//唤醒所有的线程,---java notifyAll
pthread_cond_broadcast(&cond);
//解锁
pthread_mutex_unlock(&mutex);
}
// TODO xia chen hui 2020/5/29 20:51 从队列中获取(进行消费)
void get(T &t) {
//为了保证同步的安全性,所以锁定
pthread_mutex_lock(&mutex);
//if 可能有问题,
while (queue.empty()) {
//没有数据可以消费了,所以开始等待
pthread_cond_wait(&cond, &mutex);//用if 等待之后,可能会被系统唤醒
}
//证明已经被唤醒了,开始消费
//取出首元素,得到队里中的数据
t = queue.front();
//把数据弹出去(删除)
queue.pop();
//解锁
pthread_mutex_unlock(&mutex);
}
};
#include "safe_queue_tool.h"
using namespace std;
SafeQueueClass<int> safeQueueClass;
// TODO xia chen hui 2020/5/29 21:04 模拟消费者
void *getMethod(void *pVoid) {
//非0 就是true
while (1) {
int value;
safeQueueClass.get(value); //这里value 就有值了
printf("getMethod的value =%d\n", value);
//为了结束循环,如果输入-1, 就结束
if (-1 == value) {
printf("消费者执行完毕...\n");
break;
}
}
return 0;
}
// TODO xia chen hui 2020/5/29 21:05 模拟生产者
void *setMethod(void *pVoid) {
while (1) {
printf("setMethod\n");
printf("请输入信息....\n");
int value;
cin >> value;
//为了结束循环,如果输入-1, 就结束
if (-1 == value) {
//为了让消费者可以获取-1 进行停止
safeQueueClass.add(value);
printf("生产者执行完毕...\n");
break;
}
//添加进去
safeQueueClass.add(value);
}
return 0;
}
int main() {
pthread_t pthreadGet;
pthread_t pthreadSet;
pthread_create(&pthreadGet, 0, getMethod, 0);
pthread_create(&pthreadSet, 0, setMethod, 0);
pthread_join(pthreadGet, 0);
pthread_join(pthreadSet, 0);
printf("main函数执行...\n");
return 0;
}
网友评论