before going to threading we need to check out some concepts of thread synchronization in modern computers.
- thread
- deadlock
- race condition
- spin lock
- context switching
- parallelism
- concurrency
- semaphore
- mutex
Scheduling
Cancellation
Synchronization
These day we have multi core processor thats mean we can run multiple operation at same time using multi core functionality. so fully support multithreading where you can distribute your complex task to among different threads and after finishing each task they can join main thread. In most of cases graphics manipulation handle by main thread so different child thread can accomplish the operation given to them and than get back to main thread.
so in c++ we required #include <thread> header file to access threading in c++
so let start with a very simple program this function takes two parameter and return back sum of both the parameter
int addNumber(int x,int y)
{
return x+y;
};
int main(int argc, const char * argv[]) {
//Function can be stored as a variable in c++
//inside my
cout<<"the sum is"<<addNumber(10, 10)<<endl;
return 0;
}
inside my main i calling my function addNumber which is just adding two values and returning me new value.
but all the things happening here in main thread adding
#include <iostream>
#include <thread>
#include <iostream>
#include <cmath>
using namespace std;
typedef int(*NewFunctionType)(int, int);
int addNumber(int x,int y)
{
return x+y;
};
int minusNumber(int x,int y)
{
return abs(x-y);
}
//function pointer in c++
//simple concept to store a function as a variable in c++
int main(int argc, const char * argv[]) {
//Function can be stored as a variable in c++
//inside my
addNumber(10, 20);
thread thread1(minusNumber, 10,20);
thread1.join();
return 0;
}
thread thread1(minusNumber, 10,20);
//
// classThread.hpp
// c++ thread
//
// Created by Manish on 17/07/20.
// Copyright © 2020 Manish. All rights reserved.
//
#ifndef classThread_hpp
#define classThread_hpp
#include <iostream>
#include <vector>
using namespace std;
class Student
{
private:
string name;
int age;
public:
int getAge()
{
return age;
};
void setAge(int _age)
{
age=_age;
};
void setName(string _name)
{
name=_name;
};
string getName()
{
return name;
};
void displayMe()
{
cout<<"My name is =>"<<getName()<<" "<<"My age is=>"<<getAge()<<endl;
}
void failPass(const vector<int> &marks)
{
int totalMarks=0;
for(auto m:marks)
{
totalMarks+=m;
}
if(totalMarks>100)
{
cout<<"Pass"<<endl;
}else
{
cout<<"Fail"<<endl;
}
}
};
#endif /* classThread_hpp */
//
// main.cpp
// c++ thread
//
// Created by Manish on 06/07/20.
// Copyright © 2020 Manish. All rights reserved.
//
#include <iostream>
#include <thread>
#include <iostream>
#include <cmath>
#include "classThread.hpp"
using namespace std;
//function pointer in c++
//simple concept to store a function as a variable in c++
int main(int argc, const char * argv[]) {
//create a new instance of s1
Student s1;
s1.setAge(22);
s1.setName("deepak negi");
cout<<"MY AGE=>"<<s1.getAge()<<endl;
cout<<"MY NAME=>"<<s1.getName()<<endl;
//calling member function of Student in a new thread
thread t1(&Student::displayMe,&s1);
t1.join();
cout<<"second"<<endl;
//calling other member function of student class in other thread
vector<int> marks={10,10,22,11,11};
thread t2(&Student::failPass,&s1,marks);
t2.join();
cout<<"all done i am over"<<endl;
return 0;
}
void displayMe()
{
cout<<"My name is =>"<<getName()<<" "<<"My age is=>"<<getAge()<<endl;
}
void failPass(const vector<int> &marks)
{
int totalMarks=0;
for(auto m:marks)
{
totalMarks+=m;
}
if(totalMarks>100)
{
cout<<"Pass"<<endl;
}else
{
cout<<"Fail"<<endl;
}
}
//thread with pointer
Student *s2=new Student();
s2->setAge(29);
s2->setName("manish negi");
thread t3(&Student::displayMe,s2);
t3.join();
cout<<"all done i am over"<<endl;
3. third and main concept thread safety (
Thread Synchronization Primitives
)
//
// main.cpp
// c++ thread
//
// Created by Manish on 06/07/20.
// Copyright © 2020 Manish. All rights reserved.
//
#include <iostream>
#include <thread>
#include <iostream>
#include <cmath>
#include "classThread.hpp"
#include "vector"
using namespace std;
//displayNames
vector<string> myVec;
void displayNames(const string &prefix,int max)
{
for(int i=0;i<max;i++)
{
const string name=prefix+to_string(i);
myVec.push_back(name);
}
for(auto v:myVec)
{
cout<<v<<endl;
}
cout<<"-----"<<endl;
}
int main(int argc, const char * argv[]) {
thread t1(displayNames,"hello",10);
thread t2(displayNames,"bye",10);
t1.join();
t2.join();
return 0;
}
//
// main.cpp
// c++ thread
//
// Created by Manish on 06/07/20.
// Copyright © 2020 Manish. All rights reserved.
//
#include <iostream>
#include <thread>
#include <iostream>
#include <cmath>
#include "classThread.hpp"
#include "vector"
using namespace std;
//displayNames
mutex Mutex;
vector<string> myVec;
void displayNames(const string &prefix,int max)
{
Mutex.lock();
for(int i=0;i<max;i++)
{
const string name=prefix+to_string(i);
myVec.push_back(name);
}
for(auto v:myVec)
{
cout<<v<<endl;
}
Mutex.unlock();
cout<<"-----"<<endl;
}
int main(int argc, const char * argv[]) {
thread t1(displayNames,"hello",10);
thread t2(displayNames,"bye",10);
t1.join();
t2.join();
return 0;
}
//
// main.cpp
// c++ thread
//
// Created by Manish on 06/07/20.
// Copyright © 2020 Manish. All rights reserved.
//
#include <iostream>
#include <thread>
#include <iostream>
#include <cmath>
#include "classThread.hpp"
#include "vector"
using namespace std;
//displayNames
void displayNames(vector<string> &vec,const string &prefix,int max)
{
for(int i=0;i<max;i++)
{
const string name=prefix+to_string(i);
vec.push_back(name);
}
for(auto v:vec)
{
cout<<v<<endl;
}
cout<<"-------------------"<<endl;
}
int main(int argc, const char * argv[]) {
vector<string> myVec;
displayNames(myVec, "hello",50);
for(auto v:myVec)
{
cout<<v<<endl;
}
thread t1(displayNames,std::ref(myVec),"bye",50);
t1.join();
return 0;
}
//
// main.cpp
// c++ thread
//
// Created by Manish on 06/07/20.
// Copyright © 2020 Manish. All rights reserved.
//
#include <iostream>
#include <thread>
#include <iostream>
#include <cmath>
#include "classThread.hpp"
#include "map"
using namespace std;
//displayNames
//append some students
void MapContainer(map<int,string> &myMap,int from,int total)
{
for(int i=from;i<=total;i++)
{
const string student="student"+to_string(i);
myMap[i]=student;
}
for(auto x:myMap)
{
cout<<"id: "<<x.first<<" "<<"name: "<<x.second<<endl;
}
}
void displayMap(map<int,string> &myMap)
{
for(auto x:myMap)
{
cout<<"id: "<<x.first<<" "<<"name: "<<x.second<<endl;
}
}
int main(int argc, const char * argv[]) {
map<int,string> students;
thread t1=thread(MapContainer, std::ref(students),1,5);
thread t2=thread(MapContainer, std::ref(students),6,10);
t1.join();
t2.join();
map<int,string> emps;
emps[0]="ramesh";
emps[1]="dinesh";
emps[3]="seema";
thread t3=thread(displayMap, std::ref(emps));
thread t4=thread(displayMap, std::ref(emps));
t3.join();
t4.join();
return 0;
}
//
// main.cpp
// c++ thread
//
// Created by Manish on 06/07/20.
// Copyright © 2020 Manish. All rights reserved.
//
#include <iostream>
#include <thread>
#include <iostream>
#include <cmath>
#include "classThread.hpp"
#include "map"
using namespace std;
void removeItem(map<int,string> &myMap,vector<int> &keys)
{
for(auto x:keys)
{
std::map<int,string>::iterator it=myMap.find(x);
myMap.erase(it);
}
}
int main(int argc, const char * argv[]) {
map<int,string> emps;
for(int i=1;i<100;i++)
{
emps[i]="manish"+to_string(i);
}
vector<int> vec1={1,2,3,4,5,6,7,8,9,10};
vector<int> vec2={98,97,96};
thread t3=thread(removeItem, std::ref(emps),std::ref(vec1));
thread t4=thread(removeItem, std::ref(emps),std::ref(vec2));
t3.join();
t4.join();
for(auto x:emps)
{
cout<<"id: "<<x.first<<" "<<"name: "<<x.second<<endl;
}
return 0;
}
4.std::async threading in a better way using in build std::async
std::async is a better way to deal with multithreading in c++ c++ 11 and c++ 14 and upwards version support std:::async
#include <future> std:async return a future and using future.get() you can get required result let's dive in the code
#include <thread>
#include <iostream>
#include <cmath>
//need to include #include <future> for std::async
#include <future>
#include "unordered_map"
using namespace std;
//a simple add function which accept 2 input and return the result
int addNumber(int x,int y)
{
int z=x+y;
return z;
}
//bestEmp function just accept a map reference and search out the best emp based on the empid
string bestEmp(unordered_map<int,string> &empMap,int empId)
{
string name="no good emp";
//if emp name is in unordered_map then return true either false;
unordered_map<int, string>::iterator it=empMap.find(empId);
if(it!=empMap.end())
{
name=it->second;
}
return name;
};
int main(int argc, const char * argv[]) {
//more about std::async http://www.cplusplus.com/reference/future/async/
//std::async always return a future
//std::async returm a future
future<int> fut=async(addNumber, 10,10);
//fut.get() you can get excepted result in sometime in future
cout<<fut.get()<<endl;
//launch::async runs a function always in new thread (new child thread) -------------------------------------
unordered_map<int, string> empMap;
empMap[0]="manish";
empMap[1]="sachin";
empMap[2]="deepak";
empMap[4]="seema";
empMap[5]="deepak";
future<string> fut1=async(launch::async,bestEmp,std::ref(empMap),2);
cout<<"the best emp is "<<fut1.get()<<endl;
//aunch::defer does not create a new thread and tried to run passed function in same thread (main thread in my case)
future<string> fut2=async(launch::deferred,bestEmp,std::ref(empMap),6);
cout<<"the best emp is "<<fut2.get()<<endl;
return 0;
}
A bitmask value of type launch indicating the launching policy:
#include <thread>
#include <iostream>
#include <cmath>
#include <vector>
//need to include #include <future> for std::async
#include <future>
#include "unordered_map"
using namespace std;
mutex mu;
//adding data not thread safe
unordered_map<int, string> addSomeStudents(unordered_map<int, string> &students,int start,int end)
{
mu.lock();
for(int i=start;i<=end;i++)
{
students[i]="student"+to_string(i);
}
mu.unlock();
return students;
}
//removing data
unordered_map<int, string> removeSomeStudents(unordered_map<int, string> &students,vector<int> &IDS)
{
unordered_map<int, string>::iterator it;
for(auto id:IDS)
{
it=students.find(id);
if(it!=students.end())
{
students.erase(it);
}
}
return students;
}
int main(int argc, const char * argv[]) {
unordered_map<int, string> studentMap;
future<unordered_map<int, string>> fu1=async(addSomeStudents, std::ref(studentMap),1,10);
future<unordered_map<int, string>> fu2=async(addSomeStudents, std::ref(studentMap),11,20);
unordered_map<int, string> finalStudents=fu2.get();
for(auto s:finalStudents)
{
cout<<"id: "<<s.first<<"name: "<<s.second<<endl;
}
//removing some students
cout<<"removeing some students"<<endl;
vector<int> IDS1={1,2,3,4,5,6,7,8,9,10,11,12};
vector<int> IDS2={1,2,3,4,5,6,7,8,9,10,19,20};
future<unordered_map<int, string>> fu3=async(removeSomeStudents, std::ref(studentMap),std::ref(IDS1));
future<unordered_map<int, string>> fu4=async(removeSomeStudents, std::ref(studentMap),std::ref(IDS2));
for(auto s:fu4.get())
{
cout<<"id: "<<s.first<<"name: "<<s.second<<endl;
}
return 0;
}
5. c++ std Libraries contain multiple inbuilt member function to handle the threading a better way


Comments
Post a Comment