This commit is contained in:
Light-City
2020-03-03 10:00:10 +08:00
parent 535b75acfa
commit 16c12a3bc6
38 changed files with 349 additions and 22 deletions

View File

@@ -0,0 +1,20 @@
//
// Created by light on 19-11-5.
//
#include <iostream>
#include <thread>
#include <unistd.h>
using namespace std;
void hello() {
cout << "hello world" << endl;
}
int main() {
thread t(hello);
t.join(); // must add this line otherwise will failed!
// 需要注意的是线程对象执行了join后就不再joinable了所以只能调用join一次。
return 0;
}

View File

@@ -0,0 +1,108 @@
//
// Created by light on 19-11-5.
//
#include <iostream>
#include <thread>
#include <unistd.h>
#include <cassert>
using namespace std;
class background_task {
public:
void operator()() const {
cout << "ok" << endl;
}
};
void do_something(int &i) {
cout << "do_something" << endl;
}
struct func {
int &i;
func(int &i_) : i(i_) {}
void operator()() {
for (unsigned j = 0; j < 1000000; ++j) {
do_something(i); // 1. 潜在访问隐患:悬空引用
}
}
};
// 特殊情况下的等待
void f() {
int some_local_state = 0;
func my_func(some_local_state);
std::thread t(my_func);
try {
// do_something_in_current_thread();
}
catch (...) {
t.join(); // 1
throw;
}
t.join(); // 2
}
// try catch 只能捕获轻量级错误,所以如需确保线程在函数之前结束——查看是否因为线程函数使用了局部变量的引用,
// 以及其他原因——而后再确定一下程序可能会退出的途径,无论正常与否,可以提供一个简洁的机制,来做解决这个问题。
// 一种方式是使用“资源获取即初始化方式”(RAIIResource Acquisition Is Initialization)并且提供一个类在析构函数中使用join()
// std::thread支持移动的好处是可以创建thread_guard类的实例并且拥有其线程的所有权。
class thread_guard {
std::thread &t;
public:
explicit thread_guard(std::thread &t_) :
t(t_) {}
~thread_guard() {
if (t.joinable()) // 1
{
t.join(); // 2
}
}
thread_guard(thread_guard const &) = delete; // 3
thread_guard &operator=(thread_guard const &) = delete;
};
void f1()
{
int some_local_state=0;
func my_func(some_local_state);
std::thread t(my_func);
thread_guard g(t);
// do_something_in_current_thread();
} // 4
// 当线程执行到4处时局部对象就要被逆序销毁了。因此thread_guard对象g是第一个被销毁的
// 这时线程在析构函数中被加入2到原始线程中。
// 即使do_something_in_current_thread抛出一个异常这个销毁依旧会发生。
int main() {
background_task f;
// thread t(f); // ok
// t.join();
//声明一个名为my_threadx的函数,这个函数带有一个参数(函数指针指向没有参数并返回background_task对象的函数)返回一个std::thread对象的函数
// thread my_thread1(background_task());
// 针对Most Vexing Parse问题解决如下
// thread my_thread1((background_task())); // 多组括号
// my_thread1.join();
// thread my_thread2{background_task()}; // 新的初始化语法
// my_thread2.join();
// thread myThread([](){
// cout<<"ok"<<endl;
// });
// myThread.join();
// 后台运行线程
std::thread t(f);
t.detach();
assert(!t.joinable());
return 0;
}

View File

@@ -0,0 +1,27 @@
//
// Created by light on 19-11-5.
//
#include <iostream>
#include <thread>
using namespace std;
class X {
public:
void do_length_work() {};
};
void process_big_object(std::unique_ptr<X>);
int main() {
X my_x;
thread t(&X::do_length_work, &my_x); // 1
std::unique_ptr<X> p(new X);
p->do_length_work();
std::thread tt(process_big_object,std::move(p));
//std::thread实例的可移动且不可复制性。不可复制保性证了在同一时间点
// 一个std::thread实例只能关联一个执行线程可移动性使得程序员可以自己决定哪个实例拥有实际执行线程的所有权。
return 0;
}

View File

@@ -0,0 +1,78 @@
//
// Created by light on 19-11-5.
//
#include <iostream>
#include <thread>
#include <unistd.h>
#include <vector>
#include <algorithm>
using namespace std;
void some_function() {}
void some_other_function() {}
// std::thread不支持拷贝语义。
// std::thread支持移动语义。
// scoped_thread实例
void do_something(int i) {
cout << i << endl;
}
struct func {
int &i;
func(int &i_) : i(i_) {}
void operator()() {
for (unsigned j = 0; j < 1000000; ++j) {
do_something(i);
}
}
};
class scoped_thread {
std::thread t;
public:
explicit scoped_thread(std::thread t_) : // 1
t(std::move(t_)) {
if (!t.joinable()) // 2
throw std::logic_error("No thread");
}
~scoped_thread() {
t.join(); // 3
}
scoped_thread(scoped_thread const &) = delete;
scoped_thread &operator=(scoped_thread const &) = delete;
};
void do_work(unsigned id) {}
void f() {
std::vector<std::thread> threads;
for (unsigned i = 0; i < 20; ++i) {
threads.push_back(std::thread(do_work, i)); // 产生线程
}
std::for_each(threads.begin(), threads.end(),
std::mem_fn(&std::thread::join)); // 对每个线程调用join()
}
int main() {
// std::thread t1(some_function); // 构造一个thread对象t1
// std::thread t2 = std::move(t1); // 把t1 move给另外一个thread对象t2t1不再管理之前的线程了。
// // 这句不需要std::move()从临时变量进行移动是自动和隐式的。调用的是operator=(std::thread&&)
// t1 = std::thread(some_other_function);
// std::thread t3;
// t3 = std::move(t2); // 把t2 move给t3
// // 把t3 move给t1非法。因为`t1`已经有了一个相关的线程,会调用`std::terminate()`来终止程序。
// t1 = std::move(t3);
f();
return 0;
}

View File

@@ -0,0 +1,60 @@
//
// Created by light on 19-11-5.
//
#include <iostream>
#include <algorithm>
#include <thread>
#include <vector>
#include <numeric>
using namespace std;
//使得每个线程具有最小数目的元素以避免过多的线程开销
template<typename Iterator, typename T>
struct accumulate_block {
void operator()(Iterator first, Iterator last, T &result) {
result = std::accumulate(first, last, result);
}
};
template<typename Iterator, typename T>
T parallel_accumlate(Iterator first, Iterator last, T init) {
unsigned long const length = std::distance(first, last);
if (!length)
return init;
unsigned long const min_per_thread = 25;
unsigned long const max_threads = (length + min_per_thread - 1) / min_per_thread;
cout<<max_threads<<endl;
unsigned long const hardware_threads = std::thread::hardware_concurrency();
cout<<hardware_threads<<endl;
unsigned long const num_threads = std::min(hardware_threads != 0 ? hardware_threads : 2, max_threads);
cout<<num_threads<<endl;
unsigned long const block_size = length / num_threads;
cout<<block_size<<endl;
std::vector<T> results(num_threads);
std::vector<std::thread> threads(num_threads - 1);
Iterator block_start = first;
for (unsigned long i = 0; i < (num_threads - 1); ++i) {
Iterator block_end = block_start;
std::advance(block_end, block_size);
threads[i] = std::thread(accumulate_block<Iterator, T>(), block_start, block_end, std::ref(results[i]));
block_start = block_end;
}
accumulate_block<Iterator, T>()(block_start, last, results[num_threads - 1]);
std::for_each(threads.begin(), threads.end(), std::mem_fn(&std::thread::join));
return std::accumulate(results.begin(), results.end(), init);
}
int main() {
vector<int> v{3,4,5,6};
int res=0;
cout<<parallel_accumlate(v.begin(),v.end(),res);
return 0;
}

View File

@@ -0,0 +1,34 @@
//
// Created by light on 19-11-5.
//
#include <iostream>
#include <thread>
using namespace std;
// 线程的通用标识符
std::thread::id master_thread;
void do_master_thread_work() {
cout << "master" << endl;
}
void do_common_work() {
cout << "common" << endl;
}
void some_core_part_of_algorithm() {
if (std::this_thread::get_id() == master_thread) {
do_master_thread_work();
}
do_common_work();
}
int main() {
std::cout << std::this_thread::get_id() << endl;
thread t(some_core_part_of_algorithm);
t.join();
return 0;
}