简易银行系统->多线程高并发
灵机一动整活的时候 最有写代码的动力的说:leetcode/bank_transaction at main · lvy010/leetcode
我们可以很简单的借助数组ac lc2043

C++
using namespace std;class Bank {vector<long long> b;bool ok(int a){ return 1 <= a && a <= (int)b.size(); }
public:Bank(vector<long long>& balance): b(balance) {}bool transfer(int a, int c, long long m){if(!ok(a) || !ok(c) || b[a-1] < m) return false;b[a-1] -= m; b[c-1] += m; return true;}bool deposit(int a, long long m){if(!ok(a)) return false;b[a-1] += m; return true;}bool withdraw(int a, long long m){if(!ok(a) || b[a-1] < m) return false;b[a-1] -= m; return true;}
};
那么考虑上多线程高并发应该如何进一步设计出代码呢?
- 可以采用线程池与细粒度账户级锁,按序获取双锁避免死锁,确保事务原子性与数据一致性
- 通过 future 异常传播与可配置并发度,实现高吞吐、可扩展、可观测的多线程高并发交易处理架构
thread_pool.hpp
C++
// 线程池:固定线程数,支持 submit(lambda) 返回 std::future
#pragma once#include <condition_variable>
#include <cstddef>
#include <future>
#include <mutex>
#include <queue>
#include <thread>
#include <type_traits>
#include <utility>
#include <vector>class ThreadPool {
public:explicit ThreadPool(std::size_t numThreads) {if (numThreads == 0) {numThreads = 1;}try {for (std::size_t i = 0; i < numThreads; ++i) {workers.emplace_back([this]{ this->workerLoop(); });}} catch (...) {stop();throw;}}ThreadPool(const ThreadPool&) = delete;ThreadPool& operator=(const ThreadPool&) = delete;~ThreadPool() {stop();}template <class F, class... Args,class R = std::invoke_result_t<std::decay_t<F>, std::decay_t<Args>...>>std::future<R> submit(F&& f, Args&&... args) {auto taskPtr = std::make_shared<std::packaged_task<R()>>(std::bind(std::forward<F>(f), std::forward<Args>(args)...));std::future<R> fut = taskPtr->get_future();{std::unique_lock<std::mutex> lk(mtx);if (isStopping) {throw std::runtime_error("ThreadPool stopped");}tasks.emplace([taskPtr]{try { (*taskPtr)(); } catch (...) { throw; }});}cv.notify_one();return fut;}void stop() noexcept {{std::unique_lock<std::mutex> lk(mtx);if (isStopping) return;isStopping = true;}cv.notify_all();for (std::thread& t : workers) {if (t.joinable()) t.join();}workers.clear();}private:void workerLoop() {while (true) {std::function<void()> task;{std::unique_lock<std::mutex> lk(mtx);cv.wait(lk, [this]{ return isStopping || !tasks.empty(); });if (isStopping && tasks.empty()) return;task = std::move(tasks.front());tasks.pop();}try {task();} catch (...) {// 任务异常在 future 中可见,这里不吞异常}}}std::vector<std::thread> workers;std::queue<std::function<void()>> tasks;std::mutex mtx;std::condition_variable cv;bool isStopping {false};
};
bank.cpp
C++
#pragma once#include <algorithm>
#include <cstddef>
#include <mutex>
#include <stdexcept>
#include <utility>
#include <vector>class ConcurrentBank {
public:explicit ConcurrentBank(std::vector<long long> initialBalances): balances(std::move(initialBalances)), accountMutexes(balances.size()) {}std::size_t numAccounts() const noexcept { return balances.size(); }bool deposit(std::size_t accountIndex, long long amount) {if (!isValidAccount(accountIndex) || amount <= 0) return false;std::lock_guard<std::mutex> g(accountMutexes[accountIndex]);balances[accountIndex] += amount;return true;}bool withdraw(std::size_t accountIndex, long long amount) {if (!isValidAccount(accountIndex) || amount <= 0) return false;std::lock_guard<std::mutex> g(accountMutexes[accountIndex]);if (balances[accountIndex] < amount) return false;balances[accountIndex] -= amount;return true;}bool transfer(std::size_t fromIndex, std::size_t toIndex, long long amount) {if (amount <= 0) return false;if (!isValidAccount(fromIndex) || !isValidAccount(toIndex)) return false;if (fromIndex == toIndex) return true; // 自转账视为无操作std::size_t a = std::min(fromIndex, toIndex);std::size_t b = std::max(fromIndex, toIndex);std::unique_lock<std::mutex> lockA(accountMutexes[a]);std::unique_lock<std::mutex> lockB(accountMutexes[b]);if (fromIndex == a) {if (balances[fromIndex] < amount) return false;balances[fromIndex] -= amount;balances[toIndex] += amount;} else {if (balances[fromIndex] < amount) return false;balances[fromIndex] -= amount;balances[toIndex] += amount;}return true;}long long getBalance(std::size_t accountIndex) const {if (!isValidAccount(accountIndex)) throw std::out_of_range("bad account");std::lock_guard<std::mutex> g(accountMutexes[accountIndex]);return balances[accountIndex];}long long sumBalances() const {// 顺序加锁,避免死锁for (std::size_t i = 0; i < accountMutexes.size(); ++i) {accountMutexes[i].lock();}long long s = 0;for (long long v : balances) s += v;for (std::size_t i = accountMutexes.size(); i-- > 0;) {accountMutexes[i].unlock();}return s;}private:bool isValidAccount(std::size_t accountIndex) const noexcept {return accountIndex < balances.size();}mutable std::vector<std::mutex> accountMutexes;std::vector<long long> balances;
};