C++ 两个线程之间的同步队列

C++ 两个线程之间的同步队列,c++,multithreading,c++11,C++,Multithreading,C++11,这是一个简单的程序,它有一个函数start(),等待用户输入某个内容(使用无限循环)并将其存储在队列中。start()在单独的线程中运行。用户输入某个值后,队列的大小在main中保持为零。如何同步队列? 代码:source.cpp #include <iostream> #include "kl.h" using namespace std; int main() { std::thread t1(start); while (1) { i

这是一个简单的程序,它有一个函数start(),等待用户输入某个内容(使用无限循环)并将其存储在队列中。start()在单独的线程中运行。用户输入某个值后,队列的大小在main中保持为零。如何同步队列?
代码:source.cpp

#include <iostream>
#include "kl.h"

using namespace std;

int main()
{
    std::thread t1(start);
    while (1)
    {
        if (q.size() > 0)
        {
            std::cout << "never gets inside this if\n";
            std::string first = q.front();
            q.pop();
        }           
    }
    t1.join();
}
#包括
#包括“kl.h”
使用名称空间std;
int main()
{
std::线程t1(开始);
而(1)
{
如果(q.size()>0)
{
std::cout您的代码包含一个-by-me它崩溃了;两个线程都可能在修改共享队列。(另外,您正在使用
char i
循环值高达1000-可能不是一个好主意。)

您应该使用保护共享队列,并使用通知有理由检查队列

具体地说,你应该考虑下面的情况(这对于你的情况很常见):

  • 仅在持有互斥锁时访问队列

  • 使用条件变量通知您已将某些内容推入其中

  • 使用condition变量在有点要继续处理时指定一个条件

  • 下面是对您的代码的重写:

    #include <iostream>
    #include <queue>
    #include <thread>
    #include <condition_variable>
    #include <mutex>
    
    using namespace std;
    
    std::queue<std::string> q;
    std::mutex m;
    std::condition_variable cv;
    
    void start()
    {
        string str;
        for (std::size_t i = 0; i <= 1000; i++) {
            //other stuff and str input
            std::cout << "here" << std::endl;
            std::unique_lock<std::mutex> lk(m);
            q.push(str);
            lk.unlock();
            cv.notify_one();
        }
    }
    
    int main()
    {
        std::thread t1(start);
        for (std::size_t i = 0; i <= 1000; i++)
        {
            std::unique_lock<std::mutex> lk(m);
            cv.wait(lk, []{return !q.empty();});
            std::string first = q.front();
            q.pop();    
        }
        t1.join();
    }
    
    #包括
    #包括
    #包括
    #包括
    #包括
    使用名称空间std;
    std::队列q;
    std::互斥m;
    std::条件变量cv;
    void start()
    {
    字符串str;
    
    对于(std::size\u t i=0;i我的同步队列类示例及其用法:

    template<typename T>
    class SyncQueue
    {
        std::queue<T> m_Que;
        std::mutex m_Lock;
        std::condition_variable m_ConVar;
    
    public:
        void enque(T item)
        {
            std::unique_lock<std::mutex> lock(m_Lock);
            m_Que.push(item);
            lock.unlock();
            m_ConVar.notify_all();
        }
    
        T deque()
        {
            std::unique_lock<std::mutex> lock(m_Lock);
    
            do
            {
                m_ConVar.wait(lock);
    
            } while(m_Que.size() == 0); // extra check from spontaneous notifications
    
            auto ret = m_Que.front();
            m_Que.pop();
    
            return ret;
        }
    };
    
    int main()
    {
        using namespace std::chrono_literals;
    
        SyncQueue<int> sq;
    
        std::thread consumer([&sq]()
        {
            std::cout << "consumer" << std::endl;
    
            for(;;)
            {
                std::cout << sq.deque() << std::endl;
            }
        });
    
        std::thread provider([&sq]()
        {
            std::this_thread::sleep_for(1s);
            sq.enque(1);
            std::this_thread::sleep_for(3s);
            sq.enque(2);
            std::this_thread::sleep_for(5s);
            sq.enque(3);
        });
    
        consumer.join();
    
        return 0;
    }
    
    模板
    类同步队列
    {
    std::队列m_Que;
    std::互斥m_锁;
    std::条件变量m_ConVar;
    公众:
    无效项(T项)
    {
    std::唯一的_锁锁(m_锁);
    m_Que.push(项目);
    lock.unlock();
    m_ConVar.notify_all();
    }
    T deque()
    {
    std::唯一的_锁锁(m_锁);
    做
    {
    m_ConVar.等待(锁定);
    }while(m_Que.size()==0);//来自自发通知的额外检查
    自动返回=m_Que.front();
    m_Que.pop();
    返回ret;
    }
    };
    int main()
    {
    使用名称空间std::chrono_文本;
    同步队列;
    std::线程使用者([&sq]()
    {
    
    std::cout添加了完整的代码因为你在头文件的队列上使用了“static”,实际上你有两个不同的队列,每个cpp文件中都有一个。这就是为什么main文件中的队列总是空的。@tony它显示了删除static时的链接器错误。是的,我怀疑是这样。试试extern。然后在main.cpp中尝试
    std::queue q;
    。h文件显示“这个东西在某处存在”,cpp文件说“它在这里”。更好的是,让它在main中是静态的,从头中删除它,然后通过引用将它传递到线程函数中。@tony谢谢!这个也起作用了
    #include <iostream>
    #include <queue>
    #include <thread>
    #include <condition_variable>
    #include <mutex>
    
    using namespace std;
    
    std::queue<std::string> q;
    std::mutex m;
    std::condition_variable cv;
    
    void start()
    {
        string str;
        for (std::size_t i = 0; i <= 1000; i++) {
            //other stuff and str input
            std::cout << "here" << std::endl;
            std::unique_lock<std::mutex> lk(m);
            q.push(str);
            lk.unlock();
            cv.notify_one();
        }
    }
    
    int main()
    {
        std::thread t1(start);
        for (std::size_t i = 0; i <= 1000; i++)
        {
            std::unique_lock<std::mutex> lk(m);
            cv.wait(lk, []{return !q.empty();});
            std::string first = q.front();
            q.pop();    
        }
        t1.join();
    }
    
    template<typename T>
    class SyncQueue
    {
        std::queue<T> m_Que;
        std::mutex m_Lock;
        std::condition_variable m_ConVar;
    
    public:
        void enque(T item)
        {
            std::unique_lock<std::mutex> lock(m_Lock);
            m_Que.push(item);
            lock.unlock();
            m_ConVar.notify_all();
        }
    
        T deque()
        {
            std::unique_lock<std::mutex> lock(m_Lock);
    
            do
            {
                m_ConVar.wait(lock);
    
            } while(m_Que.size() == 0); // extra check from spontaneous notifications
    
            auto ret = m_Que.front();
            m_Que.pop();
    
            return ret;
        }
    };
    
    int main()
    {
        using namespace std::chrono_literals;
    
        SyncQueue<int> sq;
    
        std::thread consumer([&sq]()
        {
            std::cout << "consumer" << std::endl;
    
            for(;;)
            {
                std::cout << sq.deque() << std::endl;
            }
        });
    
        std::thread provider([&sq]()
        {
            std::this_thread::sleep_for(1s);
            sq.enque(1);
            std::this_thread::sleep_for(3s);
            sq.enque(2);
            std::this_thread::sleep_for(5s);
            sq.enque(3);
        });
    
        consumer.join();
    
        return 0;
    }