update
This commit is contained in:
20
concurrency_v1/chapter1/1_helloworld.cpp
Normal file
20
concurrency_v1/chapter1/1_helloworld.cpp
Normal 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;
|
||||
}
|
108
concurrency_v1/chapter2/2.1_basic.cpp
Normal file
108
concurrency_v1/chapter2/2.1_basic.cpp
Normal 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 只能捕获轻量级错误,所以如需确保线程在函数之前结束——查看是否因为线程函数使用了局部变量的引用,
|
||||
// 以及其他原因——而后再确定一下程序可能会退出的途径,无论正常与否,可以提供一个简洁的机制,来做解决这个问题。
|
||||
|
||||
// 一种方式是使用“资源获取即初始化方式”(RAII,Resource 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;
|
||||
}
|
27
concurrency_v1/chapter2/2.2_transfer.cpp
Normal file
27
concurrency_v1/chapter2/2.2_transfer.cpp
Normal 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;
|
||||
}
|
78
concurrency_v1/chapter2/2.3_ownership.cpp
Normal file
78
concurrency_v1/chapter2/2.3_ownership.cpp
Normal 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对象t2,t1不再管理之前的线程了。
|
||||
// // 这句不需要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;
|
||||
}
|
60
concurrency_v1/chapter2/2.4_runtime.cpp
Normal file
60
concurrency_v1/chapter2/2.4_runtime.cpp
Normal 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;
|
||||
}
|
34
concurrency_v1/chapter2/2_5_id.cpp
Normal file
34
concurrency_v1/chapter2/2_5_id.cpp
Normal 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;
|
||||
}
|
Reference in New Issue
Block a user