代码之家  ›  专栏  ›  技术社区  ›  Andy

如何在C++中实现一个简单的多线程文件管理器?

  •  0
  • Andy  · 技术社区  · 6 年前

    为了了解C++中的多线程编程,我正在实现一个基本的多线程记录器。

    每次线程记录一条消息时;该消息被推到了deque的后面。

    在一个单独的线程中,FileLogger检查deque中是否有任何消息,如果有,则将它们写入文件。

    对deque的访问由互斥锁保护。

    为了便于从任何地方登录;记录器是作为单例实现的。

    因为实例是一个(静态)指针,指针不会改变;实例不必由互斥锁保护?

    我的代码正确吗?

    // FileLogger.h:
    class FileLogger
    {
    public:
        static void initialize(const char* filePath) { // called by main thread before any threads are spawned
            instance_ = new FileLogger(filePath);
        }
        static FileLogger* instance() { // called from many threads simultaneously
            return instance_;
        }
        void log(const std::string &msg);
    private:
        FileLogger(const char* filePath);
        void writeToFile();
        static FileLogger*     instance_;
        std::deque<std::string> messages;
        std::mutex         messagesMutex; // lock/unlock this each time messages is pushed or popped
        std::ofstream               fout;
        std::thread         writerThread;
    };
    // FileLogger.cpp:
    FileLogger* FileLogger::instance_ = nullptr;
    
    void FileLogger::writeToFile() {
        for (;;) {
            std::string message;
            while (messages.empty()) {
                std::this_thread::sleep_for(std::chrono::nanoseconds(10));
            }
            messagesMutex.lock();
            message = messages.front();
            messages.pop_front();
            messagesMutex.unlock();
            fout << message << std::endl << std::flush;
        }
    }
    
    FileLogger::FileLogger(const char* filePath) {
        fout.open(filePath);
        std::thread t(&FileLogger::writeToFile, this);
        writerThread = std::move(t);
    }
    
    void FileLogger::log(const std::string &msg) {
        std::lock_guard<std::mutex> lg(messagesMutex);
        messages.push_back(msg);
    }
    
    0 回复  |  直到 6 年前
        1
  •  1
  •   Ulrich Eckhardt    6 年前

    • 有一个指针(一个拿着你的单身汉的指针)。
    • 此指针只设置一次,然后保持不变。
    • 只有在设置指针之后,才会启动更多线程。

    在这种情况下,您不必同步对指针本身的访问。线程的启动已经起到了同步的作用:启动线程之前发生的所有写操作对线程内运行的代码都是可见的。