GitHub上的代码下载链接:github.com/WU-SUNFLOWE…
两个线程轮流打印奇偶数
#include <thread>
#include <mutex>
#include <condition_variable>
int counter = 1;
int max_counter = 100;
std::mutex mtx;
std::condition_variable cv;
void PrintOddWorker() {
while (true) {
std::unique_lock<std::mutex> locker(mtx);
cv.wait(locker, []() {
return counter % 2 == 1 || counter > max_counter;
});
if (counter > max_counter) {
break;
}
printf("PrintOddWorker: %d\n", counter);
++counter;
cv.notify_one();
}
}
void PrintEvenWorker() {
while (true) {
std::unique_lock<std::mutex> locker(mtx);
cv.wait(locker, []() {
return counter % 2 == 0 || counter > max_counter;
});
if (counter > max_counter) {
break;
}
printf("PrintEvenWorker: %d\n", counter);
++counter;
cv.notify_one();
}
}
int main() {
std::thread t1(&PrintEvenWorker);
std::thread t2(&PrintOddWorker);
t1.join();
t2.join();
printf("Main Thread Finished!\n");
}
N个线程轮流打印
#include <mutex>
#include <thread>
#include <vector>
#include <iostream>
#include <condition_variable>
int counter = 0;
const int max_counter = 50;
std::mutex mtx;
std::condition_variable cv;
void DoWork(int thread_id, int total_threads) {
while (true) {
std::unique_lock<std::mutex> locker(mtx);
{
cv.wait(locker, [total_threads, thread_id]() {
return counter % total_threads == thread_id || counter > max_counter;
});
if (counter > max_counter) {
break;
}
printf("Thread(%d) : %d\n", thread_id, counter);
++counter;
}
locker.unlock();
cv.notify_all(); // DON'T USE notify_one !!!
}
}
int main() {
const int total_threads = 5;
std::vector<std::thread> threads;
for (int i = 0; i < max_counter; ++i) {
threads.emplace_back(std::thread(&DoWork, i, total_threads));
}
for (int i = 0; i < max_counter; ++i) {
threads[i].join();
}
printf("Main Thread Finished!\n");
}
生产者消费者模型
#include <iostream>
#include <mutex>
#include <thread>
#include <queue>
#include <condition_variable>
template <typename T>
class TaskQueue {
private:
std::mutex mutex_;
size_t capacity_;
std::queue<T> queue_;
std::condition_variable is_not_full_cond_;
std::condition_variable is_not_empty_cond_;
bool IsFull() {
return queue_.size() == capacity_;
}
bool IsEmpty() {
return queue_.size() == 0;
}
public:
explicit TaskQueue(size_t capacity) : capacity_(capacity) {}
void Push(T& elem) {
std::unique_lock<std::mutex> locker(mutex_);
{
is_not_full_cond_.wait(locker, [this]() {
return !IsFull();
});
queue_.emplace(elem);
}
locker.unlock();
is_not_empty_cond_.notify_one();
}
T Pop() {
T ret;
std::unique_lock<std::mutex> locker(mutex_);
{
is_not_empty_cond_.wait(locker, [this]() {
return !IsEmpty();
});
ret = queue_.front();
queue_.pop();
}
locker.unlock();
is_not_full_cond_.notify_one();
return ret;
}
};
void Producer(TaskQueue<int>& q, int num) {
while (num-- > 0) {
int tmp = ::rand() % 100;
std::cout << "Producer: " << tmp << std::endl;
q.Push(tmp);
}
}
void Consumer(TaskQueue<int>& q, int num) {
while (num-- > 0) {
std::cout << "Consumer: " << q.Pop() << std::endl;
}
}
int main() {
::srand(::time(nullptr));
TaskQueue<int> q(10);
std::thread producer(&Producer, std::ref(q), 100);
std::thread consumer(&Consumer, std::ref(q), 100);
producer.join();
consumer.join();
}
手写线程池
#include <unistd.h>
#include <thread>
#include <iostream>
#include <mutex>
#include <thread>
#include <queue>
#include <condition_variable>
#include <memory>
template <typename T>
class TaskQueue {
private:
std::mutex mutex_;
size_t capacity_;
std::queue<T> queue_;
std::condition_variable is_not_full_cond_;
std::condition_variable is_not_empty_cond_;
bool IsFull() {
return queue_.size() == capacity_;
}
bool IsEmpty() {
return queue_.size() == 0;
}
public:
explicit TaskQueue(size_t capacity) : capacity_(capacity) {}
template<typename U>
void Push(U&& elem) {
std::unique_lock<std::mutex> locker(mutex_);
{
is_not_full_cond_.wait(locker, [this]() {
return !IsFull();
});
queue_.emplace(std::forward<U>(elem));
}
locker.unlock();
is_not_empty_cond_.notify_one();
}
T Pop() {
T ret;
std::unique_lock<std::mutex> locker(mutex_);
{
is_not_empty_cond_.wait(locker, [this]() {
return !IsEmpty();
});
ret = std::move(queue_.front());
queue_.pop();
}
locker.unlock();
is_not_full_cond_.notify_one();
return ret;
}
};
class Task {
public:
Task() {}
virtual ~Task() {}
virtual int Do() = 0;
};
class MyTask : public Task {
public:
MyTask() {}
int Do() override {
std::cout << "MyTask tid=" << ::gettid() << std::endl;
return 0;
}
};
class ExitTask : public Task {
public:
ExitTask() {}
int Do() override {
std::cout << "Thread " << ::gettid() << " exit!" << std::endl;
return -1;
}
};
class ThreadPool {
private:
std::vector<std::thread> threads_;
int thread_num_;
TaskQueue<std::unique_ptr<Task>> queue_;
public:
ThreadPool(int thread_num, int queue_size)
: thread_num_(thread_num), queue_(queue_size) {}
void Start() {
for (auto i = 0; i < thread_num_; ++i) {
threads_.emplace_back(std::thread(&ThreadPool::DoWork, this));
}
}
void Exit() {
for (auto i = 0; i < thread_num_; ++i) {
queue_.Push(std::move(std::make_unique<ExitTask>()));
}
for (auto& thread : threads_) {
thread.join();
}
}
void AddTask(std::unique_ptr<Task> task) {
queue_.Push(std::move(task));
}
private:
void DoWork() {
while (true) {
auto task = queue_.Pop();
auto ret = task->Do();
if (ret) break;
}
}
};
int main() {
ThreadPool thread_pool(4, 4);
thread_pool.Start();
for (int i = 0; i < 20; ++i) {
thread_pool.AddTask(std::make_unique<MyTask>());
}
thread_pool.Exit();
std::cout << "Main Thread Exit!" << std::endl;
return 0;
}
手写读写锁
读者优先锁
纯二值信号量(互斥锁)版本
#include <thread>
#include <mutex>
#include <iostream>
class MySharedLock {
private:
std::mutex writer_lock_;
std::mutex reader_counter_lock_;
int reader_counter_ = 0;
public:
void Lock() {
writer_lock_.lock();
}
void Unlock() {
writer_lock_.unlock();
}
void LockShared() {
reader_counter_lock_.lock();
{
++reader_counter_;
if (reader_counter_ == 1) {
writer_lock_.lock();
}
}
reader_counter_lock_.unlock();
}
void UnlockShared() {
reader_counter_lock_.lock();
{
--reader_counter_;
if (reader_counter_ == 0) {
writer_lock_.unlock();
}
}
reader_counter_lock_.unlock();
}
};
int resource = 0;
int max_resource = 1000;
MySharedLock shared_lock;
void WriterWorker() {
bool flag = true;
while (flag) {
shared_lock.Lock();
{
// Write action...
++resource;
printf("write resource=%d\n", resource);
flag = resource < max_resource;
}
shared_lock.Unlock();
}
}
void ReaderWorker() {
bool flag = true;
while (flag) {
shared_lock.LockShared();
{
// Read action...
printf("read resource=%d\n", resource);
flag = resource < max_resource;
}
shared_lock.UnlockShared();
}
}
int main() {
std::thread reader1(&ReaderWorker);
std::thread reader2(&ReaderWorker);
std::thread writer1(&WriterWorker);
std::thread writer2(&WriterWorker);
reader1.join();
reader2.join();
writer1.join();
writer2.join();
}
条件变量版本
#include <thread>
#include <mutex>
#include <iostream>
#include <condition_variable>
class MySharedLock {
private:
std::mutex mutex_;
std::condition_variable cond_read_;
std::condition_variable cond_write_;
int active_readers_ = 0;
int active_writers_ = 0;
int waiting_readers_ = 0;
int waiting_writers_ = 0;
public:
void LockShared() {
std::unique_lock<std::mutex> mtx(mutex_);
++waiting_readers_;
cond_read_.wait(mtx, [this]() {
return !(active_writers_ > 0);
});
--waiting_readers_;
++active_readers_;
}
void UnlockShared() {
std::unique_lock<std::mutex> mtx(mutex_);
if (--active_readers_ == 0 && waiting_writers_ > 0) {
cond_write_.notify_one();
}
}
void Lock() {
std::unique_lock<std::mutex> mtx(mutex_);
++waiting_writers_;
cond_write_.wait(mtx, [this]() {
return !(active_readers_ > 0 || active_writers_ > 0);
});
--waiting_writers_;
++active_writers_;
}
void Unlock() {
std::unique_lock<std::mutex> mtx(mutex_);
--active_writers_;
if (waiting_readers_ > 0) {
cond_read_.notify_all();
}
else if (waiting_writers_ > 0) {
cond_write_.notify_one();
}
}
};
int resource = 0;
int max_resource = 1000;
MySharedLock shared_lock;
void WriterWorker() {
bool flag = true;
while (flag) {
shared_lock.Lock();
{
// Write action...
++resource;
printf("write resource=%d\n", resource);
flag = resource < max_resource;
}
shared_lock.Unlock();
}
}
void ReaderWorker() {
bool flag = true;
while (flag) {
shared_lock.LockShared();
{
// Read action...
printf("read resource=%d\n", resource);
flag = resource < max_resource;
}
shared_lock.UnlockShared();
}
}
int main() {
std::thread reader1(&ReaderWorker);
std::thread reader2(&ReaderWorker);
std::thread writer1(&WriterWorker);
std::thread writer2(&WriterWorker);
reader1.join();
reader2.join();
writer1.join();
writer2.join();
}
写者优先锁
纯二值信号量(互斥锁)版本
#include <thread>
#include <mutex>
#include <iostream>
#include <condition_variable>
class MySharedLock {
private:
int reader_count_ = 0;
int writer_count_ = 0;
std::mutex reader_count_protector_;
std::mutex writer_count_protector_;
std::mutex resource_protector_;
std::mutex reader_mtx_;
public:
void Lock() {
writer_count_protector_.lock();
{
++writer_count_;
if (writer_count_ == 1) {
reader_mtx_.lock();
}
}
writer_count_protector_.unlock();
resource_protector_.lock();
}
void Unlock() {
resource_protector_.unlock();
writer_count_protector_.lock();
{
--writer_count_;
if (writer_count_ == 0) {
reader_mtx_.unlock();
}
}
writer_count_protector_.unlock();
}
void LockShared() {
reader_mtx_.lock();
{
reader_count_protector_.lock();
{
++reader_count_;
if (reader_count_ == 1) {
resource_protector_.lock();
}
}
reader_count_protector_.unlock();
}
reader_mtx_.unlock();
}
void UnlockShared() {
reader_count_protector_.lock();
{
--reader_count_;
if (reader_count_ == 0) {
resource_protector_.unlock();
}
}
reader_count_protector_.unlock();
}
};
int resource = 0;
int max_resource = 1000;
MySharedLock shared_lock;
void WriterWorker() {
bool flag = true;
while (flag) {
shared_lock.Lock();
{
// Write action...
++resource;
printf("write resource=%d\n", resource);
flag = resource < max_resource;
}
shared_lock.Unlock();
}
}
void ReaderWorker() {
bool flag = true;
while (flag) {
shared_lock.LockShared();
{
// Read action...
printf("read resource=%d\n", resource);
flag = resource < max_resource;
}
shared_lock.UnlockShared();
}
}
int main() {
std::thread reader1(&ReaderWorker);
std::thread reader2(&ReaderWorker);
std::thread writer1(&WriterWorker);
std::thread writer2(&WriterWorker);
reader1.join();
reader2.join();
writer1.join();
writer2.join();
}
条件变量版本
#include <thread>
#include <mutex>
#include <iostream>
#include <condition_variable>
class MySharedLock {
private:
std::mutex mutex_;
std::condition_variable cond_read_;
std::condition_variable cond_write_;
int active_readers_ = 0;
int active_writers_ = 0;
int waiting_readers_ = 0;
int waiting_writers_ = 0;
public:
void LockShared() {
std::unique_lock<std::mutex> mtx(mutex_);
++waiting_readers_;
cond_read_.wait(mtx, [this]() {
return !(active_writers_ > 0 || waiting_writers_ > 0);
});
--waiting_readers_;
++active_readers_;
}
void UnlockShared() {
std::unique_lock<std::mutex> mtx(mutex_);
if (--active_readers_ == 0 && waiting_writers_ > 0) {
cond_write_.notify_one();
}
}
void Lock() {
std::unique_lock<std::mutex> mtx(mutex_);
++waiting_writers_;
cond_write_.wait(mtx, [this]() {
return !(active_readers_ > 0 || active_writers_ > 0);
});
--waiting_writers_;
++active_writers_;
}
void Unlock() {
std::unique_lock<std::mutex> mtx(mutex_);
--active_writers_;
if (waiting_writers_ > 0) {
cond_write_.notify_one();
}
else if (waiting_readers_ > 0) {
cond_read_.notify_all();
}
}
};
int resource = 0;
int max_resource = 1000;
MySharedLock shared_lock;
void WriterWorker() {
bool flag = true;
while (flag) {
shared_lock.Lock();
{
// Write action...
++resource;
printf("write resource=%d\n", resource);
flag = resource < max_resource;
}
shared_lock.Unlock();
}
}
void ReaderWorker() {
bool flag = true;
while (flag) {
shared_lock.LockShared();
{
// Read action...
printf("read resource=%d\n", resource);
flag = resource < max_resource;
}
shared_lock.UnlockShared();
}
}
int main() {
std::thread reader1(&ReaderWorker);
std::thread reader2(&ReaderWorker);
std::thread writer1(&WriterWorker);
std::thread writer2(&WriterWorker);
reader1.join();
reader2.join();
writer1.join();
writer2.join();
}
公平锁
纯二值信号量(互斥锁)版本
#include <thread>
#include <mutex>
#include <iostream>
class MySharedLock {
private:
std::mutex serializer_;
std::mutex writer_lock_;
std::mutex reader_counter_lock_;
int reader_counter_ = 0;
public:
void Lock() {
serializer_.lock();
writer_lock_.lock();
serializer_.unlock();
}
void Unlock() {
writer_lock_.unlock();
}
void LockShared() {
serializer_.lock();
reader_counter_lock_.lock();
{
++reader_counter_;
if (reader_counter_ == 1) {
writer_lock_.lock();
}
}
reader_counter_lock_.unlock();
serializer_.unlock();
}
void UnlockShared() {
reader_counter_lock_.lock();
{
--reader_counter_;
if (reader_counter_ == 0) {
writer_lock_.unlock();
}
}
reader_counter_lock_.unlock();
}
};
int resource = 0;
int max_resource = 1000;
MySharedLock shared_lock;
void WriterWorker() {
bool flag = true;
while (flag) {
shared_lock.Lock();
{
// Write action...
++resource;
printf("write resource=%d\n", resource);
flag = resource < max_resource;
}
shared_lock.Unlock();
}
}
void ReaderWorker() {
bool flag = true;
while (flag) {
shared_lock.LockShared();
{
// Read action...
printf("read resource=%d\n", resource);
flag = resource < max_resource;
}
shared_lock.UnlockShared();
}
}
int main() {
std::thread reader1(&ReaderWorker);
std::thread reader2(&ReaderWorker);
std::thread writer1(&WriterWorker);
std::thread writer2(&WriterWorker);
reader1.join();
reader2.join();
writer1.join();
writer2.join();
}
条件变量版本
#include <thread>
#include <mutex>
#include <iostream>
#include <condition_variable>
class MySharedLock {
private:
std::mutex mutex_;
std::condition_variable cond_;
int active_readers_ = 0;
int next_ticket_ = 0;
int latest_ticket_ = 0;
public:
void LockShared() {
std::unique_lock<std::mutex> locker(mutex_);
int ticket = latest_ticket_++;
cond_.wait(locker, [this, ticket]() {
return ticket == next_ticket_;
});
++next_ticket_;
++active_readers_;
cond_.notify_all();
}
void UnlockShared() {
std::unique_lock<std::mutex> locker(mutex_);
--active_readers_;
cond_.notify_all();
}
void Lock() {
std::unique_lock<std::mutex> locker(mutex_);
int ticket = latest_ticket_++;
cond_.wait(locker, [this, ticket]() {
return ticket == next_ticket_ && active_readers_ <= 0;
});
}
void Unlock() {
std::unique_lock<std::mutex> locker(mutex_);
++next_ticket_;
cond_.notify_all();
}
};
int resource = 0;
int max_resource = 1000;
MySharedLock shared_lock;
void WriterWorker() {
bool flag = true;
while (flag) {
shared_lock.Lock();
{
// Write action...
++resource;
printf("write resource=%d\n", resource);
flag = resource < max_resource;
}
shared_lock.Unlock();
}
}
void ReaderWorker() {
bool flag = true;
while (flag) {
shared_lock.LockShared();
{
// Read action...
printf("read resource=%d\n", resource);
flag = resource < max_resource;
}
shared_lock.UnlockShared();
}
}
int main() {
std::thread reader1(&ReaderWorker);
std::thread reader2(&ReaderWorker);
std::thread writer1(&WriterWorker);
std::thread writer2(&WriterWorker);
reader1.join();
reader2.join();
writer1.join();
writer2.join();
}