(C++)验证累加非原子操作以及vector和thread的结合使用(附fitten code插件安装方法,AI插件,帮忙填充代码)
注:代码主要由fitten code生成,环境为visual studio2022。
插件安装方法:打开VS 正常创建一个项目,然后点击上方栏的“扩展”然后点击“扩展管理”(我已经安装了所以显示由fitten code插件,没安装的话就没有),点击后自动打开了“扩展管理器”,在“浏览”的搜索框中填入“fitten code”然后点击下载,下载后需要登陆,登录的方式很多种,登陆后就可以正常使用了。很多时候你需要些什么函数他都会自动生成,按“tab”填充即可。比如你定义一个void bubblesort(冒泡排序)或者void quicksort(),他都会给出提示,你只管"tab" "tab" "tab"......函数功能就实现了。
以下是我用ai生成的代码,少量注释和代码经过改动。
#include <iostream>
#include <thread>
#include <vector>
using namespace std;
const int NUM_THREADS = 10; // 线程数量
const int INCREMENTS_PER_THREAD = 10000000; // 每个线程的累加次数
int globalCounter = 0; // 全局计数器
//这函数是线程函数,用于执行累加操作
void addToCounter() {
for (int i = 0; i < INCREMENTS_PER_THREAD; ++i) {
globalCounter++; // 累加操作 (非原子操作)
}
}
int main() {
//创建一个动态数组,用于存放线程,数组名为threads
vector<thread> threads;
// 创建线程,并将线程添加到threads数组中
for (int i = 0; i < NUM_THREADS; ++i) {
// 启动线程,并将函数addToCounter作为线程函数传递
threads.emplace_back(addToCounter);
}
//auto& th代表自动获取threads数组中的元素类型,并创建一个引用变量th,将其绑定到threads数组中的每个元素上
//冒号左边是创建引用的类型,冒号右边是创建引用的对象
for (auto& th : threads) {
th.join();//等待线程结束
}
// 计算预期的结果,并将其存储在变量expectedValue中
int expectedValue = NUM_THREADS * INCREMENTS_PER_THREAD;
// 输出结果,并比较预期值和实际值
cout << "预期的结果(如果是原子操作): " << expectedValue << endl;
cout << "实际结果(实际上不是原子操作): " << globalCounter << endl; // 实际值(应小于预期值)
// 等待用户输入,以便查看结果
system("pause");
return 0;
}
十个线程每个线程累加1000万次,预计应该是一亿,实际却只有一千三百万、一千四百万
十个线程,每个线程加一百万次,预计结果应该在一千万,实际却是一百五十多万、一百六十多万、一百四十多万
但是如果十个线程每个只加1万次,预计结果在10万的时候,多次实验有结果是10万的,也有小于十万的。两者出现的次数差不多。可想如果再小一个数量级那就几乎不会出现由于抢占cpu而导致中断++操作