【问题标题】:Singleton class for mutex in c++C++中互斥锁的单例类
【发布时间】:2017-05-03 11:13:18
【问题描述】:

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

我在单个文件中有一个多线程应用程序(2 个类和我在其中创建线程和所有内容的真正主程序)。我想分成3个文件。每个类一个(带有它们的标题)和一个主类。

我有几个 mutice 和一个队列,用于在线程之间共享消息并随时锁定和解锁它们。

我想写一个单例类,这样他们都可以共享互斥锁:

标题:

#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;

我在这里做错了什么?

【问题讨论】:

  • 您不能按值返回std::mutex,而是按引用返回。
  • 有了这两个结果,我几乎可以正常工作了。现在我得到这个错误:/tmp/ccVyBCBk.o: In function CommonSingleton::GetMutexWB()': commonsingleton.cpp:(.text+0x47): undefined reference to CommonSingleton::mutex_w_b' collect2: error: ld returned 1 exit status

标签: c++ multithreading c++11 mutex


【解决方案1】:

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

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

就是这样,你可以从任何地方调用这个函数,它总是会返回一个对同一个互斥体的引用,它会在第一次被调用时被初始化。

【讨论】:

  • 我的投票。单例类通常是 Java 习惯的交叉训练。 C++ 仍然有文件级的函数,愿它们长存。文件级std::mutex 是一种 Python 风格(语言不是 Monty)全局解释器锁 (GIL),它可能会成为类似的瓶颈,但在这里可能没问题。
【解决方案2】:

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

首先,您不需要在函数定义中再次编写静态,因此在您的 cpp 中:

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

其次,std::mutex 已删除复制和移动构造函数,因此如果不通过引用(或 const-ref)传递现有的互斥锁,您将无法返回现有的互斥锁,这会将您的 cpp 函数转换为:

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

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

【讨论】:

    【解决方案3】:

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

    这意味着您可以在以后改变主意,无需重构。

    示例:

    #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();
    }
    

    【讨论】:

      【解决方案4】:

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

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

      static CommonSingleton& CommonSingleton::getInstance(){
      

      CommonSingleton& CommonSingleton::getInstance(){
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2022-07-31
        • 1970-01-01
        • 2015-10-06
        • 1970-01-01
        • 2018-05-23
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多