In C++ concurrent programming, the use of design patterns can improve the readability, maintainability and scalability of the code. Common patterns include: producer-consumer pattern: one thread generates data and other threads consume data. . Reader-writer mode: Multiple readers can access shared resources at the same time, but only one writer can access it. Monitor mode: protects concurrent access to shared resources, enforces synchronization and status checks. Thread pool mode: Create thread groups in advance to avoid the overhead of frequently creating and destroying threads.
Common design patterns in C++ concurrent programming
In concurrent programming, the use of design patterns can significantly improve the reliability of the code. Readability, maintainability and scalability. The following lists some common patterns in C++ concurrent programming:
Producer-Consumer Pattern
In this pattern, a producer thread generates data, And one or more consumer threads consume this data. Common implementation methods are to use queues or shared memory.
Example:
class Producer { public: void produce(const T& data) { std::lock_guard<std::mutex> lock(queue_mutex); queue.push(data); } private: std::queue<T> queue; std::mutex queue_mutex; }; class Consumer { public: void consume() { std::unique_lock<std::mutex> lock(queue_mutex); if (queue.empty()) { condition_variable.wait(lock); } const T& data = queue.front(); queue.pop(); lock.unlock(); // ... } private: std::shared_ptr<Producer> producer; std::condition_variable condition_variable; std::mutex queue_mutex; };
Reader-Writer Mode
This mode allows multiple readers to access shared resources at the same time, but Only one writer can access it. Reentrant locks or read-write locks are often used to implement this pattern.
Example:
class ReadWriteLock { public: void read_lock() { while (write_locked) { unique_lock<std::mutex> lock(read_mutex); read_count++; } } void read_unlock() { std::lock_guard<std::mutex> lock(read_mutex); read_count--; } void write_lock() { std::lock_guard<std::mutex> lock(write_mutex); while (read_count > 0) { /* 等待读完成 */} write_locked = true; } void write_unlock() { std::lock_guard<std::mutex> lock(write_mutex); write_locked = false; } private: bool write_locked = false; int read_count = 0; std::mutex read_mutex; std::mutex write_mutex; };
Monitor Pattern
Monitor pattern protects concurrency by limiting data access to a single object Access shared resources. Monitor objects encapsulate data and operations and enforce synchronization and status checking.
Example:
class Account { public: void deposit(int amount) { std::lock_guard<std::mutex> lock(balance_mutex); balance += amount; } int withdraw(int amount) { std::lock_guard<std::mutex> lock(balance_mutex); if (amount <= balance) { balance -= amount; return amount; } return 0; } int get_balance() { std::lock_guard<std::mutex> lock(balance_mutex); return balance; } private: int balance = 0; std::mutex balance_mutex; };
Thread pool mode
Thread pool mode provides a pre-created thread group that is controlled by the client Used by end threads. By using a thread pool, you can avoid the overhead of frequently creating and destroying threads.
Example:
class ThreadPool { public: ThreadPool(int num_threads) { for (int i = 0; i < num_threads; i++) { threads.emplace_back(std::thread([this] { while (true) { std::function<void()> task; { std::unique_lock<std::mutex> lock(tasks_mutex); if (tasks.empty()) { condition_variable.wait(lock); } task = std::move(tasks.front()); tasks.pop(); } task(); } })); } } void submit(std::function<void()> task) { std::lock_guard<std::mutex> lock(tasks_mutex); tasks.push(std::move(task)); condition_variable.notify_one(); } private: std::vector<std::jthread> threads; std::queue<std::function<void()>> tasks; std::mutex tasks_mutex; std::condition_variable condition_variable; };
The above is the detailed content of Common design patterns in C++ concurrent programming. For more information, please follow other related articles on the PHP Chinese website!