동시성에 대해 배우려고하고 있으며 grpc 서비스에서 작은 연결 풀을 구현하여 postgres 데이터베이스에 많은 연결을 만들어야합니다.grpc 서비스에서 연결을위한 간단한 스레드 안전 벡터
각 요청마다 새 연결을 만들지 못하도록 기본 connectionPool을 구현하려고합니다. 시작하려면 안전하게 스레드를 만들려고 시도했습니다 std::vector
. grpc 서버를 실행할 때 단일 트랜잭션이 만들어진 다음 서버가 차단되지만 계속 진행되고있는 상황을 추론 할 수는 없습니다. 나는 잔뜩 넣어
std::shared_ptr<pqxx::connection> c = safeVector_->borrow();
c->perform(SomeTransactorImpl);
safeVector_->surrender(c);
: 어떤 도움을 다음과 같이 나는 연결을 사용, 그때 ServiceA(s)
ServiceA
내부 내 서비스에 SafeVector* s = new SafeVector(4, 10);
을 통과 주에서
class SafeVector {
std::vector<pqxx::connection*> pool_;
int size_;
int max_size_;
std::mutex m_;
std::condition_variable cv_;
public:
SafeVector(int size, int max_size) : size_(size), max_size_(max_size) {
assert(size_ <= max_size_);
for (size_t i = 0; i < size; ++i) {
pool_.push_back(new pqxx::connection("some conn string"));
}
}
SafeVector(SafeVector const&)=delete; // to be implemented
SafeVector& operator=(SafeVector const&)=delete; // no assignment keeps things simple
std::shared_ptr<pqxx::connection> borrow() {
std::unique_lock<std::mutex> l(m_);
cv_.wait(l, [this]{ return !pool_.empty(); });
std::shared_ptr<pqxx::connection> res(pool_.back());
pool_.pop_back();
return res;
}
void surrender(std::shared_ptr<pqxx::connection> connection) {
std::lock_guard<std::mutex> l(m_);
pool_.push_back(connection.get());
cv_.notify_all();
}
};
을 감상 할 수있다 (1) shared_ptr 또는 (2) 다양한 잠금 구조의 핵심 개념에 대한 근본적인 오해가 있음을 확신합니다.
특히, 4 개의 연결 (내 컴퓨터의 최대 하드웨어 스레드 수)을 사용한 후 borrow()
메서드에서 연결을 반환하려고하면 seg 오류 (오류 11)가 발생합니다.
도움을 주시면 감사하겠습니다. 감사.
'surrender()'는 원시 포인터를'pool_'에 넣습니다. 그러면 '연결'은 범위를 벗어나 그 동일한 목적을 파괴합니다. 'pool_'은 매달려있는 포인터를 가지고 끝납니다. 'pool_'을 공유 포인터의 벡터로 시작하는 것이 가장 좋을 것입니다. 또는 더 나은 여전히'unique_ptr's : 설계된대로, 당신은 클라이언트가 포인터를 포기 하겠지만 여전히 사본을 자신을 위해 보관할 위험을 감수해야합니다. –
@IgorTandetnik Thanks. 매우 유용한 연습입니다. –