织芜 2024-04-04 14:55 采纳率: 70.8%
浏览 4
已结题

C++单例模式任务队列编写时遇到的问题

第四十三行std::mutex mtx一旦定义为静态成员就会出现无法解析的外部符号错误,我明白没有把这个互斥锁定义为静态成员的必要,可是也不明白为什么这样做会导致错误

#if 1

#include<iostream>
#include<thread>
#include<mutex>
#include<queue>

#define TASKS_NUM 10

class TaskQueue
{
public:
    TaskQueue(const TaskQueue& taskQueue) = delete;
    TaskQueue& operator=(const TaskQueue& taskQueue) = delete;

    static TaskQueue* getInstance() {
        return taskQueue;
    }
    bool isEmpty() {
        std::lock_guard<std::mutex> lck(mtx);
        return tasks.empty();
    }
    bool delTask() {
        std::lock_guard<std::mutex> lck(mtx);
        if (tasks.empty())return false;
        tasks.pop();
        return true;
    }
    int getTask() {
        std::lock_guard<std::mutex> lck(mtx);
        if (tasks.empty())return 0;
        int t = tasks.front();
        tasks.pop();
        return t;
    }
    void pushTask(int i) {
        std::lock_guard<std::mutex> lck(mtx);
        tasks.push(i);
    }
private:
    TaskQueue() = default;

    std::mutex mtx;
    std::queue<int> tasks;
    static TaskQueue* taskQueue;
};
TaskQueue*  TaskQueue::taskQueue = new TaskQueue;

int main() {
    TaskQueue* instance = TaskQueue::getInstance();

    std::thread tBoss([=]() {
        for (int i = 1; i < TASKS_NUM; i++) {
            instance->pushTask(i);
            std::cout << std::this_thread::get_id() << ":老板布置任务" << i << std::endl;
            std::this_thread::sleep_for(std::chrono::milliseconds(500));
            }
        });

    std::thread tEmployee([=]() {
        std::this_thread::sleep_for(std::chrono::milliseconds(200));
        while(!instance->isEmpty()) {
            int t = instance->getTask();
            std::cout << std::this_thread::get_id() << ":员工完成任务" << t << std::endl;
            std::this_thread::sleep_for(std::chrono::milliseconds(800));
        }
        });

    tBoss.join();
    tEmployee.join();
}

#endif
  • 写回答

3条回答 默认 最新

  • 关注

    下午好🌅🌅🌅
    本答案参考ChatGPT-3.5

    问题:第四十三行std::mutex mtx一旦定义为静态成员就会出现无法解析的外部符号错误,为什么会导致错误?

    解决方案:

    1. 定义为静态成员后,会导致std::mutex对象的全局唯一性,所有TaskQueue的实例都会共享同一个std::mutex对象。
    2. 如果std::mutex对象是静态的,则无法在类外部进行初始化。
    3. 在类外部初始化静态成员时,必须提供静态成员的完整定义。
    4. 在类声明中,声明静态成员变量的时候,只是在类中定义了静态成员的类型,并没有为静态成员变量分配空间。需要在类外部定义静态成员。
    5. 解决方法是在类外部定义静态成员的语法为 "类型 类名::变量名"。

    以下是修改后的代码:

    #include<iostream>
    #include<thread>
    #include<mutex>
    #include<queue>
    
    #define TASKS_NUM 10
    
    class TaskQueue
    {
    public:
        TaskQueue(const TaskQueue& taskQueue) = delete;
        TaskQueue& operator=(const TaskQueue& taskQueue) = delete;
    
        static TaskQueue* getInstance() {
            return taskQueue;
        }
    
        bool isEmpty() {
            std::lock_guard<std::mutex> lck(mtx);
            return tasks.empty();
        }
    
        bool delTask() {
            std::lock_guard<std::mutex> lck(mtx);
            if (tasks.empty()) return false;
            tasks.pop();
            return true;
        }
    
        int getTask() {
            std::lock_guard<std::mutex> lck(mtx);
            if (tasks.empty()) return 0;
            int t = tasks.front();
            tasks.pop();
            return t;
        }
    
        void pushTask(int i) {
            std::lock_guard<std::mutex> lck(mtx);
            tasks.push(i);
        }
    
    private:
        TaskQueue() = default;
    
        static std::mutex mtx;
        std::queue<int> tasks;
        static TaskQueue* taskQueue;
    };
    
    std::mutex TaskQueue::mtx;
    TaskQueue*  TaskQueue::taskQueue = new TaskQueue;
    
    int main() {
        TaskQueue* instance = TaskQueue::getInstance();
    
        std::thread tBoss([=]() { 
            for (int i = 1; i < TASKS_NUM; i++) { 
                instance->pushTask(i); 
                std::cout << std::this_thread::get_id() << ":老板布置任务" << i << std::endl; 
                std::this_thread::sleep_for(std::chrono::milliseconds(500)); 
            } 
        });
    
        std::thread tEmployee([=]() { 
            std::this_thread::sleep_for(std::chrono::milliseconds(200)); 
            while(!instance->isEmpty()) { 
                int t = instance->getTask(); 
                std::cout << std::this_thread::get_id() << ":员工完成任务" << t << std::endl; 
                std::this_thread::sleep_for(std::chrono::milliseconds(800)); 
            } 
        });
    
        tBoss.join();
        tEmployee.join();
    }
    

    请注意,我在TaskQueue类外部定义了静态成员std::mutex mtx和TaskQueue* TaskQueue::taskQueue。这样就可以解决无法解析的外部符号错误。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论 编辑记录
查看更多回答(2条)

报告相同问题?

问题事件

  • 系统已结题 4月12日
  • 已采纳回答 4月4日
  • 创建了问题 4月4日

悬赏问题

  • ¥15 curl 命令调用正常,程序调用报 java.net.ConnectException: connection refused
  • ¥20 关于web前端如何播放二次加密m3u8视频的问题
  • ¥20 spring boot集成mqtt的使用问题
  • ¥15 使用百度地图api 位置函数报错?
  • ¥15 metamask如何添加TRON自定义网络
  • ¥66 关于川崎机器人调速问题
  • ¥15 winFrom界面无法打开
  • ¥30 crossover21 ARM64版本安装软件问题
  • ¥15 mymetaobjecthandler没有进入
  • ¥15 mmo能不能做客户端怪物