C++ 中互斥锁的单例 class

Singleton class for mutex in c++

我正在努力让它工作,但似乎有一些我不完全理解的东西。

我在单个文件中有一个 multi-threaded 应用程序(2 classes 和我在其中创建线程和所有内容的真正的主程序)。我想分成 3 个文件。每个 class 一个(和他们的 header 一个)一个给 main.

我有几个 mutices 和一个 queue 可以在线程之间共享消息并随时锁定和解锁它们。

我想写一个单例 class 这样所有人都可以共享互斥量:

header:

#ifndef COMMONSINGLETON_H
#define COMMONSINGLETON_H

#include <mutex>          // std::mutex
#include <queue>

class CommonSingleton{
    private:
        static std::mutex               mutex_w_b;
        //static std::mutex               mutex_wifi_ok;
        //static std::queue <std::string> queue_w_b;

    public:
        static CommonSingleton& getInstance();
        std::mutex GetMutexWB();
        //std::mutex GetMutexWiFiOk();
        //std::queue <std::string> GetQueueWB();
    private:
        CommonSingleton() {};
        CommonSingleton(CommonSingleton const&);
        void operator=(CommonSingleton const&);
};
#endif

还有我的 .cpp 文件:

#include "commonsingleton.h"

static CommonSingleton& CommonSingleton::getInstance(){
    static CommonSingleton instance;
    return instance;
}
std::mutex CommonSingleton::GetMutexWB(){
    return mutex_w_b;
}
/*std::mutex CommonSingleton::GetMutexWiFiOk(){
    return mutex_wifi_ok;
}
std::queue <std::string> CommonSingleton::GetQueueWB(){
   return queue_w_b;
}*/

我主要用这个来测试互斥体:

CommonSingleton::getInstance().GetMutexWB.lock();

不过现在评论出来了,就是为了搞清楚怎么编译。这是我得到的错误:

commonsingleton.cpp:4:54: error: cannot declare member function ‘static 
CommonSingleton& CommonSingleton::getInstance()’ to have static linkage [-
fpermissive]
static CommonSingleton& CommonSingleton::getInstance(){
                                                  ^
commonsingleton.cpp: In member function ‘std::mutex 
CommonSingleton::GetMutexWB()’:
commonsingleton.cpp:9:12: error: use of deleted function 
‘std::mutex::mutex(const std::mutex&)’
return mutex_w_b;
            ^
In file included from commonsingleton.h:5:0,
from commonsingleton.cpp:1:
/usr/include/c++/4.8/mutex:128:5: error: declared here
mutex(const mutex&) = delete;

我在这里做错了什么?

关键字static在c++中有很多不同的含义。当您在 class 成员声明中使用它时,您将 class 成员声明为 static,但是当您在 .cpp 文件中的 class 成员定义中使用它时,您将强制静态链接它(虽然它应该有外部链接才能在不同的翻译单元中使用)。

所以在 .cpp 文件中你应该改变

static CommonSingleton& CommonSingleton::getInstance(){

CommonSingleton& CommonSingleton::getInstance(){

您有一些编译器错误,如下所示:

首先,你不需要在函数定义中再次写static,因此在你的cpp中:

CommonSingleton& CommonSingleton::getInstance(){
    static CommonSingleton instance;
    return instance;
}

其次,std::mutex 删除了复制和移动构造函数,因此您不能 return 现有互斥体而不通过引用(或 const-ref)传递它,这会将您的 cpp 函数转换为:

std::mutex& CommonSingleton::GetMutexWB(){
    return mutex_w_b;
}
std::mutex& CommonSingleton::GetMutexWiFiOk(){
    return mutex_wifi_ok;
}

确保在声明中也更改这些 (.h)

更有用的单例是客户端程序不知道它是单例的单例。

这意味着如果您希望不进行重构,您可以在以后改变主意。

示例:

#include <mutex>          // std::mutex
#include <iostream>
#include <thread>
#include <chrono>
#include <future>

// Note: This class is a singleton by internal implementation, not
// by interface. This separates the concerns of its function and its
// form, meaning client programs do not need to care.
//
class CommonSingleton{
  using mutex_type = std::mutex;
  using lock_type = std::unique_lock<mutex_type>;

private:
  struct Impl {

    mutex_type mutex_w_b;

    lock_type get_lock() { return lock_type(mutex_w_b); }

  };

  static Impl& get_impl() {
    static Impl impl {};
    return impl;
  }

public:

  lock_type get_lock() {
    return get_impl().get_lock();
  }
};


// note - copyable
void foo(CommonSingleton singleton)
{
  using namespace std::literals;
  for(int i = 0 ; i < 10000 ; ++i) {
    auto lock = singleton.get_lock();
    std::cout << "foo\n";
    lock.unlock();
    std::this_thread::sleep_for(1ms);
  }
}

void bar(CommonSingleton singleton)
{
  using namespace std::literals;
  for(int i = 0 ; i < 10000 ; ++i) {
    auto lock = singleton.get_lock();
    std::cout << "bar\n";
    lock.unlock();
    std::this_thread::sleep_for(1ms);
  }
}

void baz(CommonSingleton singleton)
{
  using namespace std::literals;
  for(int i = 0 ; i < 10000 ; ++i) {
    auto lock = singleton.get_lock();
    std::cout << "baz\n";
    lock.unlock();
    std::this_thread::sleep_for(1ms);
  }
}

int main()
{
  // all using the same mutex in reality...
  auto ffoo = std::async(std::launch::async, foo, CommonSingleton());
  auto fbar = std::async(std::launch::async, bar, CommonSingleton());
  auto fbaz = std::async(std::launch::async, baz, CommonSingleton());

  ffoo.wait();
  fbar.wait();
  fbaz.wait();
}

您不需要那么多样板文件。你只需要一个功能:

std::mutex& getCommonMutex() {
    static std::mutex m;
    return m;
}

就是这样,您可以从任何地方调用此函数,它总是 return 对同一个互斥量的引用,该互斥量将在第一次调用时被初始化。