当前位置: 代码迷 >> 综合 >> 20200102
  详细解决方案

20200102

热度:11   发布时间:2024-01-24 15:21:24.0

1 前++问题

int i = 1;

(++i)+(++i)=?

和编译器有关无固定答案,可能为6,可能为3等。

2 多线程

g++编译多线程

g++ main.cpp -o main -std=c++11 -lpthread

class A{
public:int m_count;// std::atomic<int> m_count;        //原子性包裹,防止多线程出现问题A(int vc = 0):m_count(vc){}int getCount() const { return m_count;}void setCount(){ m_count++;}
};

为了方便,全用public形式。

template <typename Iter>
void realWork(A& a,int& vVal,Iter iter1,Iter iter2){for(auto i = iter1;i != iter2;i++){vVal += *i;a.setCount();}
}

采用模板形式

void test11(){std::vector<int> arr;for(int i = 0;i < 10000000;i++){arr.push_back(rand()%100);}A a1;int Val1 = 0;realWork(a1,Val1,arr.begin(),arr.end());std::cout<<"a1.getCount() "<<a1.getCount()<<"  "<<Val1<<std::endl;
}

test11()只在单线程中跑(主线程),a1.getCount()为10000000。

void test12(){std::vector<int> arr;for(int i = 0;i < 10000000;i++){arr.push_back(rand()%100);}A a2;int Val2 = 0;
//	std::atomic<int&> Val2 = 0;auto iter1 = arr.begin() + (arr.size()/3);	//1/3分割点auto iter2 = arr.begin() + (arr.size()/3*2);	//2/3分割点auto iter3 = arr.end();std::thread t1([&a2,&Val2,iter1,iter2]{realWork(a2,Val2,iter1,iter2);});std::thread t2([&a2,&Val2,iter2,iter3]{realWork(a2,Val2,iter2,iter3);});realWork(a2,Val2,arr.begin(),iter1);t1.join();t2.join();std::cout<<"a2.getCount() "<<a2.getCount()<<"  "<<Val2<<std::endl;
}

test12()的最终结果不为10000000。void setCount(){ m_count++;}有可能多个线程同时访问m_count这个成员变量。

m_count++分为三部,内存到寄存器,寄存器运算之后,寄存器到内存。

void test13(){std::vector<int> arr;for(int i = 0;i < 10000000;i++){arr.push_back(rand()%100);}auto iter1 = arr.begin() + (arr.size()/3);	//1/3分割点auto iter2 = arr.begin() + (arr.size()/3*2);	//2/3分割点auto iter3 = arr.end();A a31;A a32;A a33;A a3;int Val31 = 0;int Val32 = 0;int Val33 = 0;int Val3 = 0;std::thread t31([&a31,&Val31,iter1,iter2]{realWork(a31,Val31,iter1,iter2);});std::thread t32([&a32,&Val32,iter2,iter3]{realWork(a32,Val32,iter2,iter3);});realWork(a33,Val33,arr.begin(),iter1);t31.join();t32.join();Val3 = Val31 + Val32 + Val33;a3.m_count = a31.m_count + a32.m_count + a33.m_count;std::cout<<"a3.getCount() "<<a3.getCount()<<"  "<<Val3<<std::endl;
}

上面把三个线程完全独立开,各自运算之后结果再汇总到一块,线程安全。

3 lambda表达式

void printAll(int a,int b,int c){std::cout<<a<<","<<b<<","<<c<<std::endl;
}void printStr(const std::string& info1,const std::string& info2){std::cout<<"info1: "<<info1<<"  info2: "<<info2<<std::endl;
} void test2(){int x = 3;int y = 4;int z = 5;std::thread t1([=]{printAll(x,y,z);});//[=] 其中=表示后面函数所需的参数,按值去拷贝t1.join();std::thread t2(printAll,x,y,z);		//函数名称,参数列表t2.join();std::string s1("abc");std::string s2("def");std::thread t5([&]{printStr(s1,s2);});		//参数都已引用的方式传参t5.join();std::thread t6(printStr,s1,s2);		//效率最低t6.join();std::thread t7(printStr,std::cref(s1),std::cref(s2));	//cref常量引用t7.join();	
}

std::thread t([=]{func(val1,val2));[=]利用该局部范围内可以使用的参数(如果线程中函数需要的话),是以赋值形式传参,即传参过程中调用拷贝构造函数。[&]是以引用的形式传参。

4 所有代码

#include <iostream>
#include <thread>
#include <vector>
#include <string>
#include <atomic>
#include <mutex>	//临界区,临界体void test0(){int i = 1;(++i)+(++i);std::cout<<i<<std::endl;
}class A{
public:
//	int m_count;std::atomic<int> m_count;		//原子性包裹,防止多线程出现问题A(int vc = 0):m_count(vc){}int getCount() const { return m_count;}void setCount(){ m_count++;}
};template <typename Iter>
void realWork(A& a,int& vVal,Iter iter1,Iter iter2){for(auto i = iter1;i != iter2;i++){vVal += *i;a.setCount();}
}void test11(){std::vector<int> arr;for(int i = 0;i < 10000000;i++){arr.push_back(rand()%100);}A a1;int Val1 = 0;realWork(a1,Val1,arr.begin(),arr.end());std::cout<<"a1.getCount() "<<a1.getCount()<<"  "<<Val1<<std::endl;
}void test12(){std::vector<int> arr;for(int i = 0;i < 10000000;i++){arr.push_back(rand()%100);}A a2;int Val2 = 0;
//	std::atomic<int&> Val2 = 0;auto iter1 = arr.begin() + (arr.size()/3);	//1/3分割点auto iter2 = arr.begin() + (arr.size()/3*2);	//2/3分割点auto iter3 = arr.end();std::thread t1([&a2,&Val2,iter1,iter2]{realWork(a2,Val2,iter1,iter2);});std::thread t2([&a2,&Val2,iter2,iter3]{realWork(a2,Val2,iter2,iter3);});realWork(a2,Val2,arr.begin(),iter1);t1.join();t2.join();std::cout<<"a2.getCount() "<<a2.getCount()<<"  "<<Val2<<std::endl;
}void test13(){std::vector<int> arr;for(int i = 0;i < 10000000;i++){arr.push_back(rand()%100);}auto iter1 = arr.begin() + (arr.size()/3);	//1/3分割点auto iter2 = arr.begin() + (arr.size()/3*2);	//2/3分割点auto iter3 = arr.end();A a31;A a32;A a33;A a3;int Val31 = 0;int Val32 = 0;int Val33 = 0;int Val3 = 0;std::thread t31([&a31,&Val31,iter1,iter2]{realWork(a31,Val31,iter1,iter2);});std::thread t32([&a32,&Val32,iter2,iter3]{realWork(a32,Val32,iter2,iter3);});realWork(a33,Val33,arr.begin(),iter1);t31.join();t32.join();Val3 = Val31 + Val32 + Val33;a3.m_count = a31.m_count + a32.m_count + a33.m_count;std::cout<<"a3.getCount() "<<a3.getCount()<<"  "<<Val3<<std::endl;
}void test1(){test11();test12();test13();
}void printAll(int a,int b,int c){std::cout<<a<<","<<b<<","<<c<<std::endl;
}void printStr(const std::string& info1,const std::string& info2){std::cout<<"info1: "<<info1<<"  info2: "<<info2<<std::endl;
} void test2(){int x = 3;int y = 4;int z = 5;std::thread t1([=]{printAll(x,y,z);});//[=] 其中=表示后面函数所需的参数,按值去拷贝t1.join();std::thread t2(printAll,x,y,z);		//函数名称,参数列表t2.join();std::string s1("abc");std::string s2("def");std::thread t5([&]{printStr(s1,s2);});		//参数都已引用的方式传参t5.join();std::thread t6(printStr,s1,s2);		//效率最低t6.join();std::thread t7(printStr,std::cref(s1),std::cref(s2));	//cref常量引用t7.join();	
}int main(){
//	test0();test1();
//	test2();return 0;
}

 

  相关解决方案