添加多线程
This commit is contained in:
parent
532b93dc95
commit
02f6a41de8
15
multi-thread/src/01_hello_thread.cpp
Normal file
15
multi-thread/src/01_hello_thread.cpp
Normal file
@ -0,0 +1,15 @@
|
||||
#include <iostream>
|
||||
#include <thread>
|
||||
|
||||
using namespace std;
|
||||
|
||||
void hello() {
|
||||
cout << "Hello World from new thread." << endl;
|
||||
}
|
||||
|
||||
int main() {
|
||||
thread t(hello);
|
||||
t.join();
|
||||
|
||||
return 0;
|
||||
}
|
14
multi-thread/src/02_lambda_thread.cpp
Normal file
14
multi-thread/src/02_lambda_thread.cpp
Normal file
@ -0,0 +1,14 @@
|
||||
#include <iostream>
|
||||
#include <thread>
|
||||
|
||||
using namespace std;
|
||||
|
||||
int main() {
|
||||
thread t([] {
|
||||
cout << "Hello World from lambda thread." << endl;
|
||||
});
|
||||
|
||||
t.join();
|
||||
|
||||
return 0;
|
||||
}
|
72
multi-thread/src/02_thread.cpp
Normal file
72
multi-thread/src/02_thread.cpp
Normal file
@ -0,0 +1,72 @@
|
||||
#include <cmath>
|
||||
#include <chrono>
|
||||
#include <iostream>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
#include <mutex>
|
||||
|
||||
using namespace std;
|
||||
|
||||
static const int MAX = 10e8;
|
||||
|
||||
static mutex gMutex;
|
||||
|
||||
static double sum = 0;
|
||||
|
||||
void worker(int min, int max) {
|
||||
for (int i = min; i <= max; i++) {
|
||||
sum += sqrt(i);
|
||||
}
|
||||
}
|
||||
|
||||
void serial_task(int min, int max) {
|
||||
auto start_time = chrono::steady_clock::now();
|
||||
sum = 0;
|
||||
worker(0, MAX);
|
||||
auto end_time = chrono::steady_clock::now();
|
||||
auto ms = chrono::duration_cast<chrono::milliseconds>(end_time - start_time).count();
|
||||
cout << "Serail task finish, " << ms << " ms consumed, Result: " << sum << endl;
|
||||
}
|
||||
|
||||
void concurrent_worker(int min, int max) {
|
||||
{
|
||||
lock_guard guard(gMutex);
|
||||
cout << "Thread " << this_thread::get_id() << " work for [" << min << ", " << max << "]" << endl;
|
||||
}
|
||||
double cur_sum = 0;
|
||||
for (int i = min; i <= max; i++) {
|
||||
cur_sum += sqrt(i);
|
||||
}
|
||||
{
|
||||
lock_guard guard(gMutex);
|
||||
sum += cur_sum;
|
||||
}
|
||||
}
|
||||
|
||||
void concurrent_task(int min, int max) {
|
||||
auto start_time = chrono::steady_clock::now();
|
||||
|
||||
unsigned concurrent_count = thread::hardware_concurrency();
|
||||
cout << "hardware_concurrency: " << concurrent_count << endl;
|
||||
vector<thread> threads;
|
||||
min = 0;
|
||||
sum = 0;
|
||||
for (int t = 0; t < concurrent_count; t++) {
|
||||
int range = max / concurrent_count * (t + 1);
|
||||
threads.push_back(thread(concurrent_worker, min, range));
|
||||
min = range + 1;
|
||||
}
|
||||
for (int i = 0; i < threads.size(); i++) {
|
||||
threads[i].join();
|
||||
}
|
||||
|
||||
auto end_time = chrono::steady_clock::now();
|
||||
auto ms = chrono::duration_cast<chrono::milliseconds>(end_time - start_time).count();
|
||||
cout << "Concurrent task finish, " << ms << " ms consumed, Result: " << sum << endl;
|
||||
}
|
||||
|
||||
int main() {
|
||||
serial_task(0, MAX);
|
||||
concurrent_task(0, MAX);
|
||||
return 0;
|
||||
}
|
16
multi-thread/src/03_thread_argument.cpp
Normal file
16
multi-thread/src/03_thread_argument.cpp
Normal file
@ -0,0 +1,16 @@
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
|
||||
using namespace std;
|
||||
|
||||
void hello(string name) {
|
||||
cout << "Welcome to " << name << endl;
|
||||
}
|
||||
|
||||
int main() {
|
||||
thread t(hello, "https://paul.pub");
|
||||
t.join();
|
||||
|
||||
return 0;
|
||||
}
|
41
multi-thread/src/04_thread_self_manage.cpp
Normal file
41
multi-thread/src/04_thread_self_manage.cpp
Normal file
@ -0,0 +1,41 @@
|
||||
#include <chrono>
|
||||
#include <ctime>
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <thread>
|
||||
|
||||
using namespace std;
|
||||
|
||||
void print_time() {
|
||||
auto now = chrono::system_clock::now();
|
||||
auto in_time_t = chrono::system_clock::to_time_t(now);
|
||||
|
||||
std::stringstream ss;
|
||||
ss << put_time(localtime(&in_time_t), "%Y-%m-%d %X");
|
||||
cout << "now is: " << ss.str() << endl;
|
||||
}
|
||||
|
||||
void sleep_thread() {
|
||||
this_thread::sleep_for(chrono::seconds(3));
|
||||
cout << "[thread-" << this_thread::get_id() << "] is waking up" << endl;
|
||||
}
|
||||
|
||||
void loop_thread() {
|
||||
for (int i = 0; i < 10; i++) {
|
||||
cout << "[thread-" << this_thread::get_id() << "] print: " << i << endl;
|
||||
}
|
||||
}
|
||||
|
||||
int main() {
|
||||
print_time();
|
||||
|
||||
thread t1(sleep_thread);
|
||||
thread t2(loop_thread);
|
||||
|
||||
t1.join();
|
||||
t2.detach();
|
||||
|
||||
print_time();
|
||||
return 0;
|
||||
}
|
28
multi-thread/src/05_call_once.cpp
Normal file
28
multi-thread/src/05_call_once.cpp
Normal file
@ -0,0 +1,28 @@
|
||||
#include <iostream>
|
||||
#include <mutex>
|
||||
#include <thread>
|
||||
|
||||
using namespace std;
|
||||
|
||||
void init() {
|
||||
cout << "Initialing..." << endl;
|
||||
// Do something...
|
||||
}
|
||||
|
||||
void worker(once_flag* flag) {
|
||||
call_once(*flag, init);
|
||||
}
|
||||
|
||||
int main() {
|
||||
once_flag flag;
|
||||
|
||||
thread t1(worker, &flag);
|
||||
thread t2(worker, &flag);
|
||||
thread t3(worker, &flag);
|
||||
|
||||
t1.join();
|
||||
t2.join();
|
||||
t3.join();
|
||||
|
||||
return 0;
|
||||
}
|
53
multi-thread/src/06_naive_multithread.cpp
Normal file
53
multi-thread/src/06_naive_multithread.cpp
Normal file
@ -0,0 +1,53 @@
|
||||
#include <cmath>
|
||||
#include <chrono>
|
||||
#include <iostream>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
|
||||
using namespace std;
|
||||
|
||||
static const int MAX = 10e8;
|
||||
static double sum = 0;
|
||||
|
||||
void worker(int min, int max) {
|
||||
for (int i = min; i <= max; i++) {
|
||||
sum += sqrt(i);
|
||||
}
|
||||
}
|
||||
|
||||
void serial_task(int min, int max) {
|
||||
auto start_time = chrono::steady_clock::now();
|
||||
sum = 0;
|
||||
worker(0, MAX);
|
||||
auto end_time = chrono::steady_clock::now();
|
||||
auto ms = chrono::duration_cast<chrono::milliseconds>(end_time - start_time).count();
|
||||
cout << "Serail task finish, " << ms << " ms consumed, Result: " << sum << endl;
|
||||
}
|
||||
|
||||
void concurrent_task(int min, int max) {
|
||||
auto start_time = chrono::steady_clock::now();
|
||||
|
||||
unsigned concurrent_count = thread::hardware_concurrency();
|
||||
cout << "hardware_concurrency: " << concurrent_count << endl;
|
||||
vector<thread> threads;
|
||||
min = 0;
|
||||
sum = 0;
|
||||
for (int t = 0; t < concurrent_count; t++) {
|
||||
int range = max / concurrent_count * (t + 1);
|
||||
threads.push_back(thread(worker, min, range));
|
||||
min = range + 1;
|
||||
}
|
||||
for (int i = 0; i < threads.size(); i++) {
|
||||
threads[i].join();
|
||||
}
|
||||
|
||||
auto end_time = chrono::steady_clock::now();
|
||||
auto ms = chrono::duration_cast<chrono::milliseconds>(end_time - start_time).count();
|
||||
cout << "Concurrent task finish, " << ms << " ms consumed, Result: " << sum << endl;
|
||||
}
|
||||
|
||||
int main() {
|
||||
serial_task(0, MAX);
|
||||
concurrent_task(0, MAX);
|
||||
return 0;
|
||||
}
|
48
multi-thread/src/07_mutex_lock.cpp
Normal file
48
multi-thread/src/07_mutex_lock.cpp
Normal file
@ -0,0 +1,48 @@
|
||||
#include <chrono>
|
||||
#include <cmath>
|
||||
#include <iostream>
|
||||
#include <mutex>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
|
||||
using namespace std;
|
||||
|
||||
static const int MAX = 10e8;
|
||||
static double sum = 0;
|
||||
|
||||
static mutex exclusive;
|
||||
|
||||
void concurrent_worker(int min, int max) {
|
||||
for (int i = min; i <= max; i++) {
|
||||
exclusive.lock();
|
||||
sum += sqrt(i);
|
||||
exclusive.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
void concurrent_task(int min, int max) {
|
||||
auto start_time = chrono::steady_clock::now();
|
||||
|
||||
unsigned concurrent_count = thread::hardware_concurrency();
|
||||
cout << "hardware_concurrency: " << concurrent_count << endl;
|
||||
vector<thread> threads;
|
||||
min = 0;
|
||||
sum = 0;
|
||||
for (int t = 0; t < concurrent_count; t++) {
|
||||
int range = max / concurrent_count * (t + 1);
|
||||
threads.push_back(thread(concurrent_worker, min, range));
|
||||
min = range + 1;
|
||||
}
|
||||
for (int i = 0; i < threads.size(); i++) {
|
||||
threads[i].join();
|
||||
}
|
||||
|
||||
auto end_time = chrono::steady_clock::now();
|
||||
auto ms = chrono::duration_cast<chrono::milliseconds>(end_time - start_time).count();
|
||||
cout << "Concurrent task finish, " << ms << " ms consumed, Result: " << sum << endl;
|
||||
}
|
||||
|
||||
int main() {
|
||||
concurrent_task(0, MAX);
|
||||
return 0;
|
||||
}
|
50
multi-thread/src/08_improved_mutex_lock.cpp
Normal file
50
multi-thread/src/08_improved_mutex_lock.cpp
Normal file
@ -0,0 +1,50 @@
|
||||
#include <cmath>
|
||||
#include <chrono>
|
||||
#include <iostream>
|
||||
#include <mutex>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
|
||||
using namespace std;
|
||||
|
||||
static const int MAX = 10e8;
|
||||
static double sum = 0;
|
||||
|
||||
static mutex exclusive;
|
||||
|
||||
void concurrent_worker(int min, int max) {
|
||||
double tmp_sum = 0;
|
||||
for (int i = min; i <= max; i++) {
|
||||
tmp_sum += sqrt(i);
|
||||
}
|
||||
exclusive.lock();
|
||||
sum += tmp_sum;
|
||||
exclusive.unlock();
|
||||
}
|
||||
|
||||
void concurrent_task(int min, int max) {
|
||||
auto start_time = chrono::steady_clock::now();
|
||||
|
||||
unsigned concurrent_count = thread::hardware_concurrency();
|
||||
cout << "hardware_concurrency: " << concurrent_count << endl;
|
||||
vector<thread> threads;
|
||||
min = 0;
|
||||
sum = 0;
|
||||
for (int t = 0; t < concurrent_count; t++) {
|
||||
int range = max / concurrent_count * (t + 1);
|
||||
threads.push_back(thread(concurrent_worker, min, range));
|
||||
min = range + 1;
|
||||
}
|
||||
for (int i = 0; i < threads.size(); i++) {
|
||||
threads[i].join();
|
||||
}
|
||||
|
||||
auto end_time = chrono::steady_clock::now();
|
||||
auto ms = chrono::duration_cast<chrono::milliseconds>(end_time - start_time).count();
|
||||
cout << "Concurrent task finish, " << ms << " ms consumed, Result: " << sum << endl;
|
||||
}
|
||||
|
||||
int main() {
|
||||
concurrent_task(0, MAX);
|
||||
return 0;
|
||||
}
|
93
multi-thread/src/09_deadlock_bank_transfer.cpp
Normal file
93
multi-thread/src/09_deadlock_bank_transfer.cpp
Normal file
@ -0,0 +1,93 @@
|
||||
#include <iostream>
|
||||
#include <mutex>
|
||||
#include <set>
|
||||
#include <thread>
|
||||
|
||||
using namespace std;
|
||||
|
||||
class Account {
|
||||
public:
|
||||
Account(string name, double money): mName(name), mMoney(money) {};
|
||||
|
||||
public:
|
||||
void changeMoney(double amount) {
|
||||
mMoney += amount;
|
||||
}
|
||||
string getName() {
|
||||
return mName;
|
||||
}
|
||||
double getMoney() {
|
||||
return mMoney;
|
||||
}
|
||||
mutex* getLock() {
|
||||
return &mMoneyLock;
|
||||
}
|
||||
|
||||
private:
|
||||
string mName;
|
||||
double mMoney;
|
||||
mutex mMoneyLock;
|
||||
};
|
||||
|
||||
class Bank {
|
||||
public:
|
||||
void addAccount(Account* account) {
|
||||
mAccounts.insert(account);
|
||||
}
|
||||
|
||||
bool transferMoney(Account* accountA, Account* accountB, double amount) {
|
||||
lock_guard guardA(*accountA->getLock());
|
||||
lock_guard guardB(*accountB->getLock());
|
||||
|
||||
if (amount > accountA->getMoney()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
accountA->changeMoney(-amount);
|
||||
accountB->changeMoney(amount);
|
||||
return true;
|
||||
}
|
||||
|
||||
double totalMoney() const {
|
||||
double sum = 0;
|
||||
for (auto a : mAccounts) {
|
||||
sum += a->getMoney();
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
private:
|
||||
set<Account*> mAccounts;
|
||||
};
|
||||
|
||||
void randomTransfer(Bank* bank, Account* accountA, Account* accountB) {
|
||||
while(true) {
|
||||
double randomMoney = ((double)rand() / RAND_MAX) * 100;
|
||||
if (bank->transferMoney(accountA, accountB, randomMoney)) {
|
||||
cout << "Transfer " << randomMoney << " from " << accountA->getName()
|
||||
<< " to " << accountB->getName()
|
||||
<< ", Bank totalMoney: " << bank->totalMoney() << endl;
|
||||
} else {
|
||||
cout << "Transfer failed, "
|
||||
<< accountA->getName() << " has only $" << accountA->getMoney() << ", but "
|
||||
<< randomMoney << " required" << endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main() {
|
||||
Account a("Paul", 100);
|
||||
Account b("Moira", 100);
|
||||
|
||||
Bank aBank;
|
||||
aBank.addAccount(&a);
|
||||
aBank.addAccount(&b);
|
||||
|
||||
thread t1(randomTransfer, &aBank, &a, &b);
|
||||
thread t2(randomTransfer, &aBank, &b, &a);
|
||||
|
||||
t1.join();
|
||||
t2.join();
|
||||
|
||||
return 0;
|
||||
}
|
101
multi-thread/src/10_improved_bank_transfer.cpp
Normal file
101
multi-thread/src/10_improved_bank_transfer.cpp
Normal file
@ -0,0 +1,101 @@
|
||||
#include <iostream>
|
||||
#include <mutex>
|
||||
#include <set>
|
||||
#include <thread>
|
||||
|
||||
using namespace std;
|
||||
|
||||
class Account {
|
||||
public:
|
||||
Account(string name, double money): mName(name), mMoney(money) {};
|
||||
|
||||
public:
|
||||
void changeMoney(double amount) {
|
||||
mMoney += amount;
|
||||
}
|
||||
string getName() {
|
||||
return mName;
|
||||
}
|
||||
double getMoney() {
|
||||
return mMoney;
|
||||
}
|
||||
mutex* getLock() {
|
||||
return &mMoneyLock;
|
||||
}
|
||||
|
||||
private:
|
||||
string mName;
|
||||
double mMoney;
|
||||
mutex mMoneyLock;
|
||||
};
|
||||
|
||||
class Bank {
|
||||
public:
|
||||
void addAccount(Account* account) {
|
||||
mAccounts.insert(account);
|
||||
}
|
||||
|
||||
bool transferMoney(Account* accountA, Account* accountB, double amount) {
|
||||
// lock(*accountA->getLock(), *accountB->getLock());
|
||||
// lock_guard lockA(*accountA->getLock(), adopt_lock);
|
||||
// lock_guard lockB(*accountB->getLock(), adopt_lock);
|
||||
|
||||
scoped_lock lockAll(*accountA->getLock(), *accountB->getLock());
|
||||
|
||||
if (amount > accountA->getMoney()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
accountA->changeMoney(-amount);
|
||||
accountB->changeMoney(amount);
|
||||
return true;
|
||||
}
|
||||
|
||||
double totalMoney() const {
|
||||
double sum = 0;
|
||||
for (auto a : mAccounts) {
|
||||
sum += a->getMoney();
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
private:
|
||||
set<Account*> mAccounts;
|
||||
};
|
||||
|
||||
mutex sCoutLock;
|
||||
void randomTransfer(Bank* bank, Account* accountA, Account* accountB) {
|
||||
while(true) {
|
||||
double randomMoney = ((double)rand() / RAND_MAX) * 100;
|
||||
if (bank->transferMoney(accountA, accountB, randomMoney)) {
|
||||
sCoutLock.lock();
|
||||
cout << "Transfer " << randomMoney << " from " << accountA->getName()
|
||||
<< " to " << accountB->getName()
|
||||
<< ", Bank totalMoney: " << bank->totalMoney() << endl;
|
||||
sCoutLock.unlock();
|
||||
} else {
|
||||
sCoutLock.lock();
|
||||
cout << "Transfer failed, "
|
||||
<< accountA->getName() << " has only " << accountA->getMoney() << ", but "
|
||||
<< randomMoney << " required" << endl;
|
||||
sCoutLock.unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main() {
|
||||
Account a("Paul", 100);
|
||||
Account b("Moira", 100);
|
||||
|
||||
Bank aBank;
|
||||
aBank.addAccount(&a);
|
||||
aBank.addAccount(&b);
|
||||
|
||||
thread t1(randomTransfer, &aBank, &a, &b);
|
||||
thread t2(randomTransfer, &aBank, &b, &a);
|
||||
|
||||
t1.join();
|
||||
t2.join();
|
||||
|
||||
return 0;
|
||||
}
|
91
multi-thread/src/11_bank_transfer_wait_notify.cpp
Normal file
91
multi-thread/src/11_bank_transfer_wait_notify.cpp
Normal file
@ -0,0 +1,91 @@
|
||||
#include <condition_variable>
|
||||
#include <iostream>
|
||||
#include <mutex>
|
||||
#include <set>
|
||||
#include <thread>
|
||||
|
||||
using namespace std;
|
||||
|
||||
class Account {
|
||||
public:
|
||||
Account(string name, double money): mName(name), mMoney(money) {};
|
||||
|
||||
public:
|
||||
void changeMoney(double amount) {
|
||||
unique_lock lock(mMoneyLock);
|
||||
mConditionVar.wait(lock, [this, amount] {
|
||||
return mMoney + amount > 0;
|
||||
});
|
||||
mMoney += amount;
|
||||
mConditionVar.notify_all();
|
||||
}
|
||||
|
||||
string getName() {
|
||||
return mName;
|
||||
}
|
||||
|
||||
double getMoney() {
|
||||
return mMoney;
|
||||
}
|
||||
|
||||
private:
|
||||
string mName;
|
||||
double mMoney;
|
||||
mutex mMoneyLock;
|
||||
condition_variable mConditionVar;
|
||||
};
|
||||
|
||||
class Bank {
|
||||
public:
|
||||
void addAccount(Account* account) {
|
||||
mAccounts.insert(account);
|
||||
}
|
||||
|
||||
void transferMoney(Account* accountA, Account* accountB, double amount) {
|
||||
accountA->changeMoney(-amount);
|
||||
accountB->changeMoney(amount);
|
||||
}
|
||||
|
||||
double totalMoney() const {
|
||||
double sum = 0;
|
||||
for (auto a : mAccounts) {
|
||||
sum += a->getMoney();
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
private:
|
||||
set<Account*> mAccounts;
|
||||
};
|
||||
|
||||
mutex sCoutLock;
|
||||
void randomTransfer(Bank* bank, Account* accountA, Account* accountB) {
|
||||
while(true) {
|
||||
double randomMoney = ((double)rand() / RAND_MAX) * 100;
|
||||
{
|
||||
lock_guard guard(sCoutLock);
|
||||
cout << "Try to Transfer " << randomMoney
|
||||
<< " from " << accountA->getName() << "(" << accountA->getMoney()
|
||||
<< ") to " << accountB->getName() << "(" << accountB->getMoney()
|
||||
<< "), Bank totalMoney: " << bank->totalMoney() << endl;
|
||||
}
|
||||
bank->transferMoney(accountA, accountB, randomMoney);
|
||||
}
|
||||
}
|
||||
|
||||
int main() {
|
||||
Account a("Paul", 100);
|
||||
Account b("Moira", 100);
|
||||
|
||||
Bank aBank;
|
||||
aBank.addAccount(&a);
|
||||
aBank.addAccount(&b);
|
||||
|
||||
thread t1(randomTransfer, &aBank, &a, &b);
|
||||
thread t2(randomTransfer, &aBank, &b, &a);
|
||||
|
||||
t1.join();
|
||||
t2.join();
|
||||
|
||||
return 0;
|
||||
}
|
63
multi-thread/src/12_async_task.cpp
Normal file
63
multi-thread/src/12_async_task.cpp
Normal file
@ -0,0 +1,63 @@
|
||||
#include <cmath>
|
||||
#include <chrono>
|
||||
#include <future>
|
||||
#include <iostream>
|
||||
#include <thread>
|
||||
|
||||
using namespace std;
|
||||
|
||||
static const int MAX = 10e8;
|
||||
static double sum = 0;
|
||||
|
||||
void worker(int min, int max) {
|
||||
for (int i = min; i <= max; i++) {
|
||||
sum += sqrt(i);
|
||||
}
|
||||
}
|
||||
|
||||
class Worker {
|
||||
public:
|
||||
Worker(int min, int max): mMin(min), mMax(max) {}
|
||||
double work() {
|
||||
mResult = 0;
|
||||
for (int i = mMin; i <= mMax; i++) {
|
||||
mResult += sqrt(i);
|
||||
}
|
||||
return mResult;
|
||||
}
|
||||
double getResult() {
|
||||
return mResult;
|
||||
}
|
||||
|
||||
private:
|
||||
int mMin;
|
||||
int mMax;
|
||||
double mResult;
|
||||
};
|
||||
|
||||
int main() {
|
||||
sum = 0;
|
||||
auto f1 = async(worker, 0, MAX);
|
||||
cout << "Async task triggered" << endl;
|
||||
f1.wait();
|
||||
cout << "Async task finish, result: " << sum << endl << endl;
|
||||
|
||||
double result = 0;
|
||||
cout << "Async task with lambda triggered, thread: " << this_thread::get_id() << endl;
|
||||
auto f2 = async(launch::async, [&result]() {
|
||||
cout << "Lambda task in thread: " << this_thread::get_id() << endl;
|
||||
for (int i = 0; i <= MAX; i++) {
|
||||
result += sqrt(i);
|
||||
}
|
||||
});
|
||||
f2.wait();
|
||||
cout << "Async task with lambda finish, result: " << result << endl << endl;
|
||||
|
||||
Worker w(0, MAX);
|
||||
cout << "Task in class triggered" << endl;
|
||||
auto f3 = async(&Worker::work, &w);
|
||||
f3.wait();
|
||||
cout << "Task in class finish, result: " << w.getResult() << endl << endl;
|
||||
|
||||
return 0;
|
||||
}
|
52
multi-thread/src/13_packaged_task.cpp
Normal file
52
multi-thread/src/13_packaged_task.cpp
Normal file
@ -0,0 +1,52 @@
|
||||
#include <cmath>
|
||||
#include <future>
|
||||
#include <iostream>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
|
||||
using namespace std;
|
||||
|
||||
static const int MAX = 10e8;
|
||||
|
||||
double concurrent_worker(int min, int max) {
|
||||
double sum = 0;
|
||||
for (int i = min; i <= max; i++) {
|
||||
sum += sqrt(i);
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
double concurrent_task(int min, int max) {
|
||||
vector<future<double>> results;
|
||||
|
||||
unsigned concurrent_count = thread::hardware_concurrency();
|
||||
min = 0;
|
||||
for (int i = 0; i < concurrent_count; i++) {
|
||||
packaged_task<double(int, int)> task(concurrent_worker);
|
||||
results.push_back(task.get_future());
|
||||
|
||||
int range = max / concurrent_count * (i + 1);
|
||||
thread t(std::move(task), min, range);
|
||||
t.detach();
|
||||
|
||||
min = range + 1;
|
||||
}
|
||||
|
||||
cout << "threads create finish" << endl;
|
||||
double sum = 0;
|
||||
for (auto& r : results) {
|
||||
sum += r.get();
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
int main() {
|
||||
auto start_time = chrono::steady_clock::now();
|
||||
|
||||
double r = concurrent_task(0, MAX);
|
||||
|
||||
auto end_time = chrono::steady_clock::now();
|
||||
auto ms = chrono::duration_cast<chrono::milliseconds>(end_time - start_time).count();
|
||||
cout << "Concurrent task finish, " << ms << " ms consumed, Result: " << r << endl;
|
||||
return 0;
|
||||
}
|
55
multi-thread/src/14_promise_future.cpp
Normal file
55
multi-thread/src/14_promise_future.cpp
Normal file
@ -0,0 +1,55 @@
|
||||
#include <cmath>
|
||||
#include <future>
|
||||
#include <iostream>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
|
||||
using namespace std;
|
||||
|
||||
static const int MAX = 10e8;
|
||||
|
||||
double concurrent_worker(int min, int max) {
|
||||
double sum = 0;
|
||||
for (int i = min; i <= max; i++) {
|
||||
sum += sqrt(i);
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
void concurrent_task(int min, int max, promise<double>* result) {
|
||||
vector<future<double>> results;
|
||||
|
||||
unsigned concurrent_count = thread::hardware_concurrency();
|
||||
min = 0;
|
||||
for (int i = 0; i < concurrent_count; i++) {
|
||||
packaged_task<double(int, int)> task(concurrent_worker);
|
||||
results.push_back(task.get_future());
|
||||
|
||||
int range = max / concurrent_count * (i + 1);
|
||||
thread t(std::move(task), min, range);
|
||||
t.detach();
|
||||
|
||||
min = range + 1;
|
||||
}
|
||||
|
||||
cout << "threads create finish" << endl;
|
||||
double sum = 0;
|
||||
for (auto& r : results) {
|
||||
sum += r.get();
|
||||
}
|
||||
result->set_value(sum);
|
||||
cout << "concurrent_task finish" << endl;
|
||||
}
|
||||
|
||||
int main() {
|
||||
auto start_time = chrono::steady_clock::now();
|
||||
|
||||
promise<double> sum;
|
||||
concurrent_task(0, MAX, &sum);
|
||||
|
||||
auto end_time = chrono::steady_clock::now();
|
||||
auto ms = chrono::duration_cast<chrono::milliseconds>(end_time - start_time).count();
|
||||
cout << "Concurrent task finish, " << ms << " ms consumed." << endl;
|
||||
cout << "Result: " << sum.get_future().get() << endl;
|
||||
return 0;
|
||||
}
|
44
multi-thread/src/15_parallel_algorithm.cpp
Normal file
44
multi-thread/src/15_parallel_algorithm.cpp
Normal file
@ -0,0 +1,44 @@
|
||||
#include <algorithm>
|
||||
#include <chrono>
|
||||
#include <execution>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <random>
|
||||
|
||||
using namespace std;
|
||||
|
||||
void generateRandomData(vector<double>& collection, int size) {
|
||||
random_device rd;
|
||||
mt19937 mt(rd());
|
||||
uniform_real_distribution<double> dist(1.0, 100.0);
|
||||
for (int i = 0; i < size; i++) {
|
||||
collection.push_back(dist(mt));
|
||||
}
|
||||
}
|
||||
|
||||
int main() {
|
||||
vector<double> collection;
|
||||
generateRandomData(collection, 10e6);
|
||||
|
||||
vector<double> copy1(collection);
|
||||
vector<double> copy2(collection);
|
||||
vector<double> copy3(collection);
|
||||
|
||||
auto time1 = chrono::steady_clock::now();
|
||||
sort(execution::seq, copy1.begin(), copy1.end());
|
||||
auto time2 = chrono::steady_clock::now();
|
||||
auto duration = chrono::duration_cast<chrono::milliseconds>(time2 - time1).count();
|
||||
cout << "Sequenced sort consuming " << duration << "ms." << endl;
|
||||
|
||||
auto time3 = chrono::steady_clock::now();
|
||||
sort(execution::par, copy2.begin(),copy2.end());
|
||||
auto time4 = chrono::steady_clock::now();
|
||||
duration = chrono::duration_cast<chrono::milliseconds>(time4 - time3).count();
|
||||
cout << "Parallel sort consuming " << duration << "ms." << endl;
|
||||
|
||||
auto time5 = chrono::steady_clock::now();
|
||||
sort(execution::par_unseq, copy2.begin(),copy2.end());
|
||||
auto time6 = chrono::steady_clock::now();
|
||||
duration = chrono::duration_cast<chrono::milliseconds>(time6 - time5).count();
|
||||
cout << "Parallel unsequenced sort consuming " << duration << "ms." << endl;
|
||||
}
|
58
multi-thread/src/CMakeLists.txt
Normal file
58
multi-thread/src/CMakeLists.txt
Normal file
@ -0,0 +1,58 @@
|
||||
cmake_minimum_required(VERSION 3.8)
|
||||
project(cpp-concurrency)
|
||||
|
||||
#set(CMAKE_CXX_COMPILER "g++-9")
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ./bin)
|
||||
|
||||
add_executable(hello_thread 01_hello_thread.cpp)
|
||||
add_executable(lambda_thread 02_lambda_thread.cpp)
|
||||
add_executable(thread 02_thread.cpp)
|
||||
add_executable(thread_argument 03_thread_argument.cpp)
|
||||
add_executable(thread_self_manage 04_thread_self_manage.cpp)
|
||||
add_executable(call_once 05_call_once.cpp)
|
||||
add_executable(naive_multithread 06_naive_multithread.cpp)
|
||||
add_executable(mutex_lock 07_mutex_lock.cpp)
|
||||
add_executable(improved_mutex_lock 08_improved_mutex_lock.cpp)
|
||||
add_executable(deadlock_bank_transfer 09_deadlock_bank_transfer.cpp)
|
||||
add_executable(improved_bank_transfer 10_improved_bank_transfer.cpp)
|
||||
add_executable(bank_transfer_wait_notify 11_bank_transfer_wait_notify.cpp)
|
||||
add_executable(async_task 12_async_task.cpp)
|
||||
add_executable(packaged_task 13_packaged_task.cpp)
|
||||
add_executable(promise_future 14_promise_future.cpp)
|
||||
|
||||
# For OS X
|
||||
if(APPLE)
|
||||
if (DEFINED ENV{tbb_path})
|
||||
message("tbb_path=" $ENV{tbb_path})
|
||||
include_directories($ENV{tbb_path}/include/)
|
||||
link_directories($ENV{tbb_path}/lib/)
|
||||
add_executable(parallel_algorithm 15_parallel_algorithm.cpp)
|
||||
target_link_libraries(parallel_algorithm tbb)
|
||||
else()
|
||||
message("[Warning] 'tbb_path' not defined, 'export tbb_path=xxx' to build parallel algorithm.")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# For Linux
|
||||
IF("${CMAKE_SYSTEM}" MATCHES "Linux")
|
||||
add_executable(parallel_algorithm 15_parallel_algorithm.cpp)
|
||||
target_link_libraries(parallel_algorithm tbb)
|
||||
target_link_libraries(hello_thread pthread)
|
||||
target_link_libraries(lambda_thread pthread)
|
||||
target_link_libraries(thread_argument pthread)
|
||||
target_link_libraries(thread_self_manage pthread)
|
||||
target_link_libraries(call_once pthread)
|
||||
target_link_libraries(naive_multithread pthread)
|
||||
target_link_libraries(mutex_lock pthread)
|
||||
target_link_libraries(improved_mutex_lock pthread)
|
||||
target_link_libraries(deadlock_bank_transfer pthread)
|
||||
target_link_libraries(improved_bank_transfer pthread)
|
||||
target_link_libraries(bank_transfer_wait_notify pthread)
|
||||
target_link_libraries(async_task pthread)
|
||||
target_link_libraries(packaged_task pthread)
|
||||
target_link_libraries(promise_future pthread)
|
||||
endif()
|
||||
|
Loading…
Reference in New Issue
Block a user