如何使用任意字符串作为C ++中的锁? [英] How do I use an arbitrary string as a lock in C++?

查看:104
本文介绍了如何使用任意字符串作为C ++中的锁?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我有一个多线程C ++程序,以函数调用 handleRequest(string key)的形式处理请求。每个对 handleRequest 的调用发生在一个单独的线程中,并且 key 的任意大的可能值。 / p>

我想要以下行为:




  • 同时呼叫 c> 全部序列化是



handleRequest 的正文可能如下所示:

  void handleRequest(string key){
KeyLock lock(key);
//处理请求。
}

问题: $ c> KeyLock 以获得所需的行为?



一个简单的实现可能从这样开始:

  KeyLock :: KeyLock(string key){
global_lock-> Lock();
internal_lock_ = global_key_map [key];
if(internal_lock_ == NULL){
internal_lock_ = new Lock();
global_key_map [key] = internal_lock_;
}
global_lock-> Unlock();
internal_lock _-> Lock();
}

KeyLock ::〜KeyLock(){
internal_lock _-> Unlock();
//如果没有其他线程正在等待它,则从g​​lobal_key_map中删除internal_lock_。
}

...但是这需要在每个开头和结尾有一个全局锁请求以及为每个请求创建单独的 Lock 对象。如果对 handleRequest 的调用之间的争用很高,这可能不是问题,但是如果争用较低,它可能会产生很多开销。

解决方案

你可以做一些类似于你在你的问题,但不是一个global_key_map有几个(可能在一个数组或向量) - 哪一个



这样,而不是单个全局锁,你可以将它扩展到多个独立的锁。



这是一个经常在内存分配器中使用的模式(我不知道模式是否有名称 - 它应该)。当一个请求进来时,某些东西决定了该分配将来自哪个池(通常是请求的大小,但其他参数也可以考虑),那么只有该池需要被锁定。如果分配请求来自将使用不同池的另一个线程,则没有锁争用。


Let's say I have a multithreaded C++ program that handles requests in the form of a function call to handleRequest(string key). Each call to handleRequest occurs in a separate thread, and there are an arbitrarily large number of possible values for key.

I want the following behavior:

  • Simultaneous calls to handleRequest(key) are serialized when they have the same value for key.
  • Global serialization is minimized.

The body of handleRequest might look like this:

void handleRequest(string key) {
    KeyLock lock(key);
    // Handle the request.
}

Question: How would I implement KeyLock to get the required behavior?

A naive implementation might start off like this:

KeyLock::KeyLock(string key) {
    global_lock->Lock();
    internal_lock_ = global_key_map[key];
    if (internal_lock_  == NULL) {
        internal_lock_  = new Lock();
        global_key_map[key] = internal_lock_;
    }
    global_lock->Unlock();
    internal_lock_->Lock();
}

KeyLock::~KeyLock() {
    internal_lock_->Unlock();
    // Remove internal_lock_ from global_key_map iff no other threads are waiting for it.
}

...but that requires a global lock at the beginning and end of each request, and the creation of a separate Lock object for each request. If contention is high between calls to handleRequest, that might not be a problem, but it could impose a lot of overhead if contention is low.

解决方案

You could do something similar to what you have in your question, but instead of a single global_key_map have several (probably in an array or vector) - which one is used is determined by some simple hash function on the string.

That way instead of a single global lock, you spread that out over several independent ones.

This is a pattern that is often used in memory allocators (I don't know if the pattern has a name - it should). When a request comes in, something determines which pool the allocation will come from (usually the size of the request, but other parameters can factor in as well), then only that pool needs to be locked. If an allocation request comes in from another thread that will use a different pool, there's no lock contention.

这篇关于如何使用任意字符串作为C ++中的锁?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆