C++ 同時プログラミングでは、デザイン パターンを採用すると、コードの可読性、保守性、スケーラビリティが向上します。 一般的なパターンには次のようなものがあります。 プロデューサー / コンシューマー パターン: 1 つのスレッドがデータを生成し、他のスレッドがデータを消費します。リーダー/ライター モード: 複数のリーダーが共有リソースに同時にアクセスできますが、アクセスできるのは 1 人のライターのみです。モニター モード: 共有リソースへの同時アクセスを保護し、同期とステータス チェックを強制します。スレッド プール モード: スレッドの頻繁な作成と破棄によるオーバーヘッドを回避するために、事前にスレッド グループを作成します。
C++ 同時プログラミングの一般的なデザイン パターン
同時プログラミングでは、デザイン パターンを使用すると、コードの可読性、保守性、スケーラビリティが大幅に向上します。 C++ 同時プログラミングの一般的なパターンを以下に示します。
プロデューサー/コンシューマー パターン
このパターンでは、1 つのプロデューサー スレッドがデータを生成し、1 つ以上のコンシューマー スレッドがデータを消費します。一般的な実装方法は、キューまたは共有メモリを使用することです。
例:
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; };
リーダー/ライターモード
このモードでは、複数のリーダーが共有リソースに同時にアクセスできますが、アクセスできるのは 1 人のライターのみです。このパターンを実装するには、再入可能ロックまたは読み取り/書き込みロックがよく使用されます。
例:
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 パターン
Monitor パターンは、データ アクセスを 1 つのオブジェクトに制限することで、共有リソースへの同時アクセスを保護します。モニター オブジェクトはデータと操作をカプセル化し、同期とステータスのチェックを強制します。
例:
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; };
スレッドプールモード
スレッドプールモードは、クライアントスレッドで使用される事前に作成されたスレッドグループを提供します。スレッド プールを使用すると、スレッドの頻繁な作成と破棄によるオーバーヘッドを回避できます。
例:
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; };
以上がC++ 同時プログラミングの一般的な設計パターンの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。