目录
创建线程的三种不同方法
需包含头文件
#include <thread>
使用函数指针创建线程
#include <iostream>
#include <thread>
void thread_function()
{
for (int i = 0; i < 1000000000; i++);
std::cout << "thread function Executing" << std::endl;
}
int main()
{
std::thread threadObj(thread_function);
std::cout << "Display From MainThread" << std::endl;
threadObj.join(); // 等待线程结束
std::cout << "Exit of Main function" << std::endl;
return 0;
}
使用函数对象创建线程
#include <iostream>
#include <thread>
class DisplayThread
{
public:
void operator()()
{
for (int i = 0; i < 100000; i++)
std::cout << "Display Thread Executing" << std::endl;
}
};
int main()
{
std::thread threadObj((DisplayThread()));
for (int i = 0; i < 100000; i++)
std::cout << "Display From Main Thread " << std::endl;
std::cout << "Waiting For Thread to complete" << std::endl;
threadObj.join();
std::cout << "Exiting from Main Thread" << std::endl;
return 0;
}
使用 Lambda 函数创建线程
#include <iostream>
#include <thread>
int main()
{
std::thread threadObj([] {
for (int i = 0; i < 10000; i++)
std::cout << "Display Thread Executing" << std::endl;
});
for (int i = 0; i < 10000; i++)
std::cout << "Display From Main Thread" << std::endl;
threadObj.join();
std::cout << "Exiting from Main Thread" << std::endl;
return 0;
}
区分线程
#include <iostream>
#include <thread>
void thread_function()
{
std::cout << "Inside Thread :: ID = " << std::this_thread::get_id() << std::endl;
}
int main()
{
std::thread threadObj1(thread_function);
std::thread threadObj2(thread_function);
if (threadObj1.get_id() != threadObj2.get_id())
std::cout << "Both Threads have different IDs" << std::endl;
for (int i = 0; i < 1000000000; i++);
std::cout << "From Main Thread :: ID of Thread 1 = " << threadObj1.get_id() << std::endl;
std::cout << "From Main Thread :: ID of Thread 2 = " << threadObj2.get_id() << std::endl;
threadObj1.join(); // id需要在join之前获取,否则会变成0
threadObj2.join();
return 0;
}
join和detach线程
std::thread::join()
#include <iostream>
#include <thread>
#include <vector> // vector
#include <algorithm> // for_each
#include <functional> // mem_fn
class WorkerThread
{
public:
void operator()()
{
std::cout << "Worker Thread " << std::this_thread::get_id() << " is Executing" << std::endl;
}
};
int main()
{
std::vector<std::thread> threadList;
for (int i = 0; i < 10; i++)
{
threadList.push_back(std::thread(WorkerThread()));
}
// Now wait for all the worker thread to finish i.e.
// Call join() function on each of the std::thread object
std::cout << "wait for all the worker thread to finish" << std::endl;
std::for_each(threadList.begin(), threadList.end(), std::mem_fn(&std::thread::join));
std::cout << "Exiting from Main Thread" << std::endl;
return 0;
}
std::thread::detach()
#include <iostream>
#include <thread>
void my_fun()
{
for (int i = 0; i < 10000; i++);
std::cout << "my function end." << std::endl;
}
int main()
{
std::thread my_thread(my_fun);
std::cout << "detaching" << std::endl;
my_thread.detach(); // 线程独立运行,两边数据不互通
std::cout << my_thread.get_id() << "is detached" << std::endl; // 无法获取id
std::cout << "main end." << std::endl;
return 0;
}
小心在线程句柄上调用 detach() 和 join()
- join或者detach之前先要检查joinable,只能二选一,只能用一次
- 主进程结束之前要二选一
使用RAII
#include <iostream>
#include <thread>
class ThreadRAII
{
std::thread& m_thread;
public:
ThreadRAII(std::thread& threadObj) : m_thread(threadObj)
{
}
~ThreadRAII()
{
// Check if thread is joinable then detach the thread
if (m_thread.joinable())
{
m_thread.join();
// m_thread.detach();
}
}
};
void thread_function()
{
for (int i = 0; i < 10000; i++);
std::cout << "thread_function Executing" << std::endl;
}
int main()
{
std::thread threadObj(thread_function);
// for (int i = 0; i < 1000000; i++);
// If we comment this Line, then program will crash
ThreadRAII wrapperObj(threadObj);
return 0;
}
小心地将参数传递给线程
在C++11中将简单参数传递给std::thread
#include <iostream>
#include <string>
#include <thread>
void threadCallback(int x, std::string str)
{
std::cout << "Passed Number = " << x << std::endl;
std::cout << "Passed String = " << str << std::endl;
}
int main()
{
int x = 10;
std::string str = "Sample String";
std::thread threadObj(threadCallback, x, str);
threadObj.join();
return 0;
}
如何错误地将参数传递给C++11中的线程
p指向的数据有可能被销毁
#include <iostream>
#include <thread>
void newThreadCallback(int* p)
{
std::cout << "Inside Thread : "" : p = " << *p << std::endl;
*p = 19;
std::chrono::milliseconds dura(1000);
std::this_thread::sleep_for(dura);
std::cout << "Inside Thread : "" : p = " << *p << std::endl;
}
void startNewThread()
{
int i = 10;
std::cout << "Inside Main Thread : "" : i = " << i << std::endl;
std::thread t(newThreadCallback, &i);
t.detach();
std::cout << "Inside Main Thread : "" : i = " << i << std::endl;
}
int main()
{
startNewThread();
std::chrono::milliseconds dura(2000);
std::this_thread::sleep_for(dura);
return 0;
}
调用变量时有可能已经delete
#include <iostream>
#include <thread>
void newThreadCallback(int* p)
{
std::cout << "Inside Thread : "" : *p = " << *p << std::endl;
std::chrono::milliseconds dura(1000);
std::this_thread::sleep_for(dura);
*p = 19;
}
void startNewThread()
{
int* p = new int();
*p = 10;
std::cout << "Inside Main Thread : "" : *p = " << *p << std::endl;
std::thread t(newThreadCallback, p);
t.detach();
delete p;
p = NULL;
}
int main()
{
startNewThread();
std::chrono::milliseconds dura(2000);
std::this_thread::sleep_for(dura);
return 0;
}
如何在C++11中传递对std::thread的引用
错误示例,修改仅限于线程内
#include <iostream>
#include <thread>
void threadCallback(int const& x) // 此处一定要加const,否则报错,估计是先传值,再把值传引用
{
int& y = const_cast<int&>(x);
y++;
std::cout << "Inside Thread x = " << x << std::endl; // 10
}
int main()
{
int x = 9;
std::cout << "In Main Thread : Before Thread Start x = " << x << std::endl; // 9
std::thread threadObj(threadCallback, x);
threadObj.join();
std::cout << "In Main Thread : After Thread Joins x = " << x << std::endl; // 9
return 0;
}
正确操作
#include <iostream>
#include <thread>
void threadCallback(int & x)
{
x++;
std::cout << "Inside Thread x = " << x << std::endl;
}
int main()
{
int x = 9;
std::cout << "In Main Thread : Before Thread Start x = " << x << std::endl;
std::thread threadObj(threadCallback, std::ref(x));
threadObj.join();
std::cout << "In Main Thread : After Thread Joins x = " << x << std::endl;
return 0;
}
https://www.cnblogs.com/chen-cs/p/13056703.html
将指向类的成员函数的指针分配为线程函数:
#include <iostream>
#include <thread>
class DummyClass {
public:
DummyClass():y(0)
{}
DummyClass(const DummyClass& obj):y(obj.y)
{}
void sampleMemberFunction(int x)
{
std::cout << "Inside sampleMemberFunction " << x << std::endl;
std::cout << "Inside sampleMemberFunction " << y << std::endl;
y++;
}
int y;
};
int main() {
DummyClass dummyObj;
int x = 10;
dummyObj.y = 5;
std::thread threadObj1(&DummyClass::sampleMemberFunction, &dummyObj, x);
std::thread threadObj2(&DummyClass::sampleMemberFunction, &dummyObj, x);
threadObj1.join();
threadObj2.join();
return 0;
}
数据共享和竞争条件
线程1 | 线程2 |
将“mMoney”加载到寄存器 | |
将“mMoney”加载到寄存器 | |
将寄存器的值加一 | |
将寄存器的值加一 | |
将寄存器的值存到“mMoney”中 | |
将寄存器的值存到“mMoney”中 |
#include <iostream>
#include <vector>
#include <thread>
// race condition
class Wallet
{
int mMoney;
public:
Wallet() :mMoney(0) {}
int getMoney() { return mMoney; }
void addMoney(int money)
{
for (int i = 0; i < money; ++i)
{
mMoney++;
}
}
};
int testMultithreadedWallet()
{
Wallet walletObject;
std::vector<std::thread> threads;
for (int i = 0; i < 10; ++i) {
threads.push_back(std::thread(&Wallet::addMoney, &walletObject, 1000));
}
for (int i = 0; i < threads.size(); i++)
{
threads.at(i).join();
}
return walletObject.getMoney();
}
int main()
{
int val = 0;
int k = 0;
while(true)
{
if ((val = testMultithreadedWallet()) != 10000)
{
std::cout << "Error at count = " << k << " Money in Wallet = " << val << std::endl;
break;
}
k++;
}
return 0;
}
使用互斥锁处理竞争条件
需包含的头文件
#include<mutex>
一般用法
#include<iostream>
#include<thread>
#include<vector>
#include<mutex>
class Wallet
{
int mMoney;
std::mutex mutex;
public:
Wallet() :mMoney(0) {}
int getMoney() { return mMoney; }
void addMoney(int money)
{
mutex.lock(); // 如果mutex处于lock状态,lock()指令就会等待mutex.unlock()
for (int i = 0; i < money; ++i)
{
mMoney++;
}
mutex.unlock();
}
};
lock_guard(RAII)
#include<iostream>
#include<thread>
#include<vector>
#include<mutex>
class Wallet
{
int mMoney;
std::mutex mutex;
public:
Wallet() :mMoney(0) {}
int getMoney() { return mMoney; }
void addMoney(int money)
{
std::lock_guard<std::mutex> lockGuard(mutex);
// In constructor it locks the mutex
for (int i = 0; i < money; ++i)
{
// If some exception occurs at this
// poin then destructor of lockGuard
// will be called due to stack unwinding.
//
mMoney++;
}
// Once function exits, then destructor
// of lockGuard Object will be called.
// In destructor it unlocks the mutex.
}
};
公共部分
int testMultithreadedWallet()
{
Wallet walletObject;
std::vector<std::thread> threads;
for (int i = 0; i < 5; ++i) {
threads.push_back(std::thread(&Wallet::addMoney, &walletObject, 1000));
}
for (int i = 0; i < threads.size(); i++)
{
threads.at(i).join();
}
return walletObject.getMoney();
}
int main()
{
int val = 0;
for (int k = 0; k < 1000; k++)
{
if ((val = testMultithreadedWallet()) != 5000)
{
std::cout << "Error at count = " << k << " Money in Wallet = " << val << std::endl;
//break;
}
}
return 0;
}
事件处理

使用互斥锁
#include<iostream>
#include<thread>
#include<mutex>
// boolean check loop
class Application
{
std::mutex m_mutex;
bool m_bDataLoaded;
public:
Application()
{
m_bDataLoaded = false;
}
void loadData()
{
// Make This Thread sleep for 1 Second
std::cout << "Loading Data from XML" << std::endl;
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
// Lock The Data structure
std::lock_guard<std::mutex> guard(m_mutex);
// Set the flag to true, means data is loaded
m_bDataLoaded = true;
}
void mainTask()
{
std::cout << "Do Some Handshaking" << std::endl;
// Acquire the Lock
m_mutex.lock();
// Check if flag is set to true or not
while (m_bDataLoaded != true)
{
// Release the lock
m_mutex.unlock();
//sleep for 100 milli seconds
std::this_thread::sleep_for(std::chrono::milliseconds(100));
// Acquire the lock
m_mutex.lock();
}
// Release the lock
m_mutex.unlock();
//Doc processing on loaded Data
std::cout << "Do Processing On loaded Data" << std::endl;
}
};
int main()
{
Application app;
std::thread thread_1(&Application::mainTask, &app);
std::thread thread_2(&Application::loadData, &app);
thread_2.join();
thread_1.join();
return 0;
}
条件变量
需包含的头文件
#include <condition_variable>
例子同上,但是条件变量
#include <iostream>
#include <thread>
#include <functional>
#include <mutex>
#include <condition_variable>
using namespace std::placeholders;
class Application
{
std::mutex m_mutex;
std::condition_variable m_condVar;
bool m_bDataLoaded;
public:
Application()
{
m_bDataLoaded = false;
}
void loadData()
{
// Make This Thread sleep for 1 Second
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
std::cout << "Loading Data from XML" << std::endl;
// Lock The Data structure
std::lock_guard<std::mutex> guard(m_mutex);
// Set the flag to true, means data is loaded
m_bDataLoaded = true;
// Notify the condition variable
m_condVar.notify_one();
}
bool isDataLoaded()
{
return m_bDataLoaded;
}
void mainTask()
{
std::cout << "Do Some Handshaking" << std::endl;
// Acquire the lock
std::unique_lock<std::mutex> mlock(m_mutex);
// Start waiting for the Condition Variable to get signaled
// Wait() will internally release the lock and make the thread to block
// As soon as condition variable get signaled, resume the thread and
// again acquire the lock. Then check if condition is met or not
// If condition is met then continue else again go in wait.
m_condVar.wait(mlock, std::bind(&Application::isDataLoaded, this)); // 后面的条件函数并不是必要的
std::cout << "Do Processing On loaded Data" << std::endl;
}
};
int main()
{
Application app;
std::thread thread_1(&Application::mainTask, &app);
std::thread thread_2(&Application::loadData, &app);
thread_2.join();
thread_1.join();
return 0;
}
std::future,std::promise和从线程返回值
需包含的头文件
#include <future>

#include <iostream>
#include <thread>
#include <future>
void initiazer(std::promise<int>* promObj)
{
std::this_thread::sleep_for(std::chrono::seconds(1));
std::cout << "Inside Thread" << std::endl;
promObj->set_value(35);
}
int main()
{
std::promise<int> promiseObj;
std::future<int> futureObj = promiseObj.get_future();
std::thread th(initiazer, &promiseObj);
std::cout << futureObj.get() << std::endl;
th.join();
return 0;
}