添加多线程

This commit is contained in:
朱毅骏 2021-09-22 15:58:11 +08:00
parent 532b93dc95
commit 02f6a41de8
17 changed files with 894 additions and 0 deletions

View 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;
}

View 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;
}

View 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;
}

View 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;
}

View 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;
}

View 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;
}

View 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;
}

View 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;
}

View 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;
}

View 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;
}

View 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;
}

View 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;
}

View 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;
}

View 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;
}

View 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;
}

View 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;
}

View 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()