C++11 中引入了对 线程的支持 了,使得 C++ 在 并行编程时 不需要依赖第三方库
而且在原子操作中还引入了 原子类 的概念。要使用标准库中的线程,必须包含 < thread > 头文件
函数名
|
功能
|
thread()
|
构造一个线程对象,没有关联任何线程函数,即没有启动任何线程
|
thread(fn, args1, args2, ...)
|
构造一个线程对象,并关联线程函数fn,args1,args2,...为线程函数的
参数
|
get_id()
|
获取线程id
|
jionable()
|
线程是否还在执行,joinable代表的是一个正在执行中的线程。
|
jion()
|
该函数调用后会 阻塞住线程 ,当该线程结束后,主线程继续执行
|
detach()
|
在创建线程对象后马上调用,用于把被创建线程与线程对象分离开,分离
的线程变为后台线程,创建的线程的"死活"就与主线程无关
|
#include
using namespace std;
#include
void ThreadFunc(int a)
{
cout << "Thread1" << a << endl;
}
class TF
{
public:
void operator()()
{
cout << "Thread3" << endl;
}
};
int main()
{
// 线程函数为函数指针
thread t1(ThreadFunc, 10);
// 线程函数为lambda表达式
thread t2([](){cout << "Thread2" << endl; });
// 线程函数为函数对象
TF tf;
thread t3(tf);
t1.join();
t2.join();
t3.join();
cout << "Main thread!" << endl;
return 0;
}
#include
#include
#include
#include
#include
#include
using namespace std;
void Print(int n, int& x,mutex& mtx)
{
for (int i = 0; i < n; ++i)
{
mtx.lock();
cout <
#include
#include
#include
#include
#include
#include
using namespace std;
int main()
{
mutex mtx;
int x = 0;
int n = 10;
int m;
cin >> m;
vector v(m);
//v.resize(m);
for (int i = 0; i < m; ++i)
{
// 移动赋值给vector中线程对象
v[i] = thread([&](){
for (int i = 0; i < n; ++i)
{
mtx.lock();
cout << this_thread::get_id() << ":" << i << endl;
std::this_thread::sleep_for(std::chrono::milliseconds(100));
++x;
mtx.unlock();
}
});
}
for (auto& t : v)
{
t.join();
}
cout << x << endl;
return 0;
}
多线程最主要的问题是共享数据带来的问题 ( 即线程安全 )
当一个或多个线程要 修改 共享数据时,就会产生很多潜在的麻烦
#include
#include
#include
#include
#include
#include
using namespace std;
int main()
{
mutex mtx;
atomic x = 0;
// int x = 0;
int n = 1000000;
int m;
cin >> m;
vector v(m);
for (int i = 0; i < m; ++i)
{
// 移动赋值给vector中线程对象
v[i] = thread([&](){
for (int i = 0; i < n; ++i)
{
// t1 t2 t3 t4
++x;
}
});
}
for (auto& t : v)
{
t.join();
}
cout << x << endl;
return 0;
}
#include
int main()
{
atomic a1(0);
//atomic a2(a1); // 编译失败
atomic a2(0);
//a2 = a1; // 编译失败
return 0;
}
在 多线程 环境下, 原子性 只能保证 某个变量的安全性
在多线程环境下,而需要保证一段代码的安全性,就只能通过加锁的方式实现
#include
#include
#include
#include
#include
#include
using namespace std;
//RAII
template
class LockGuard
{
public:
LockGuard(Lock& lk)
:_lock(lk)
{
_lock.lock();
cout << "thread:" << this_thread::get_id() << "加锁" << endl;
}
~LockGuard()
{
cout << "thread:" << this_thread::get_id() << "解锁" << endl << endl;
_lock.unlock();
}
private:
Lock& _lock;// 成员变量是引用
};
int main()
{
mutex mtx;
atomic x = 0;
//int x = 0;
int n = 100;
int m;
cin >> m;
vector v(m);
for (int i = 0; i < m; ++i)
{
// 移动赋值给vector中线程对象
v[i] = thread([&](){
for (int i = 0; i < n; ++i)
{
{
lock_guard lk(mtx);
cout << this_thread::get_id() << ":" << i << endl;
}
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
});
}
for (auto& t : v)
{
t.join();
}
cout << x << endl;
return 0;
}
#include
#include
#include
#include
#include
#include
using namespace std;
int main()
{
int i = 0;
int n = 100;
mutex mtx;
thread t1([&](){
while (i < n)
{
mtx.lock();
cout << this_thread::get_id() << ":" << i << endl;
i += 1;
mtx.unlock();
}
});
this_thread::sleep_for(chrono::microseconds(100));
thread t2([&](){
while (i < n)
{
mtx.lock();
cout << this_thread::get_id() << ":" << i << endl;
i += 1;
mtx.unlock();
}
});
t1.join();
t2.join();
return 0;
}
#include
#include
#include
#include
#include
#include
using namespace std;
int main()
{
int i = 0;
int n = 100;
mutex mtx;
condition_variable cv;// 条件变量
bool ready = true;
// t1打印奇数
thread t1([&](){
while (i < n)
{
{
unique_lock lock(mtx);
cv.wait(lock, [&ready](){return !ready; });// 等待线程
cout << "t1--" << this_thread::get_id() << ":" << i << endl;
i += 1;
ready = true;
cv.notify_one();// 解除线程等待
}
//this_thread::yield();
this_thread::sleep_for(chrono::microseconds(100));
}
});
// t2打印偶数
thread t2([&]() {
while (i < n)
{
unique_lock lock(mtx);
cv.wait(lock, [&ready](){return ready; });
cout <<"t2--"<
#include
#include
#include
#include
#include
#include
using namespace std;
namespace bit
{
template
class shared_ptr
{
public:
shared_ptr(T* ptr = nullptr)
:_ptr(ptr)
, _pRefCount(new int(1))
, _pMutex(new mutex)
{}
shared_ptr(const shared_ptr& sp)
:_ptr(sp._ptr)
, _pRefCount(sp._pRefCount)
, _pMutex(sp._pMutex)
{
AddRef();
}
void Release()
{
bool flag = false;
_pMutex->lock();
if (--(*_pRefCount) == 0 && _ptr)
{
cout << "delete:" << _ptr << endl;
delete _ptr;
delete _pRefCount;
flag = true;
}
_pMutex->unlock();
if (flag)
delete _pMutex;
}
void AddRef()
{
_pMutex->lock();
++(*_pRefCount);
_pMutex->unlock();
}
shared_ptr& operator=(const shared_ptr& sp)
{
if (_ptr != sp._ptr)
{
Release();
_ptr = sp._ptr;
_pRefCount = sp._pRefCount;
_pMutex = sp._pMutex;
AddRef();
}
return *this;
}
int use_count()
{
return *_pRefCount;
}
~shared_ptr()
{
Release();
}
// 像指针一样使用
T& operator*()
{
return *_ptr;
}
T* operator->()
{
return _ptr;
}
T* get() const
{
return _ptr;
}
private:
T* _ptr;
int* _pRefCount;// 使用时需要加锁
mutex* _pMutex;// 锁指针
};
}
int main()
{
// shared_ptr是线程安全的吗?
bit::shared_ptr sp1(new double(1.11));
bit::shared_ptr sp2(sp1);
mutex mtx;
vector v(2);
int n = 100000;
for (auto& t : v)
{
t = thread([&](){
for (size_t i = 0; i < n; ++i)
{
// 拷贝是线程安全的
bit::shared_ptr sp(sp1);
// 访问资源不是
mtx.lock();
(*sp)++;
mtx.unlock();
}
});
}
for (auto& t : v)
{
t.join();
}
cout << sp1.use_count() << endl;
cout << *sp1 << endl;
return 0;
}
在多线程中,shared_ptr也应该对自己的引用计数进行加锁处理
#include
#include
#include
using namespace std;
class Singleton
{
public:
static Singleton* GetInstance()
{
// 保护第一次,后续不需要加锁
// 双检查加锁
if (_pInstance == nullptr)
{
unique_lock lock(_mtx);
if (_pInstance == nullptr)
{
_pInstance = new Singleton;
}
}
return _pInstance;
}
private:
// 构造函数私有
Singleton(){};
// C++11
Singleton(Singleton const&) = delete;
Singleton& operator=(Singleton const&) = delete;
static Singleton* _pInstance;
static mutex _mtx;
};
Singleton* Singleton::_pInstance = nullptr;
mutex Singleton::_mtx;
int main()
{
Singleton::GetInstance();
Singleton::GetInstance();
return 0;
}
#include
#include
#include
using namespace std;
class Singleton
{
public:
static Singleton* GetInstance()
{
static Singleton _s;// 局部的静态对象,第一次调用时初始化
return &_s;
}
private:
// 构造函数私有
Singleton() {};
// C++11
Singleton(Singleton const&) = delete;
Singleton& operator=(Singleton const&) = delete;
};
int main()
{
Singleton::GetInstance();
Singleton::GetInstance();
return 0;
}