C++ wait/notify机制

C++ wait/notify机制

notify_one:唤醒等待线程中的一个,唤醒的线程顺序执行。
notify_all:唤醒所有等待的线程,唤醒的线程抢占式执行。
wait:等待。需要其它的接口来唤醒。

instance analysis

#include <iostream>
#include <thread>
#include <condition_variable>
#include <mutex>//demo
#include <unistd.h>

std::mutex mtx_syn;
std::condition_variable cv_syn;
std::condition_variable cv_syn_1;
bool ready = false;//线程A

void threadA(int id)
{
    while (1)
    {
        std::unique_lock<std::mutex> lck(mtx_syn);
        while (!ready)
        {
            cv_syn.wait(lck);
        }
        // ...
        std::cout << "threadA " << id << '\n';
        usleep(500*1000);
        cv_syn.notify_one();   // 唤醒等待线程中的一个
        cv_syn.wait(lck);      // 等待
    }

}// 线程B
void threadB(int id)
{
    while (1)
    {
        //新创建的 unique_lock 对象管理 Mutex 对象 m,并尝试调用 m.lock() 对 Mutex 对象进行上锁,如果此时另外某个 unique_lock 对象已经管理了该 Mutex 对象 m,则当前线程将会被阻塞
        std::unique_lock<std::mutex> lck(mtx_syn);
        while (!ready)
        {
            cv_syn.wait(lck);
        }
        // ...
        std::cout << "threadB " << id << '\n';
        usleep(500*1000);
	cv_syn.notify_one();// 唤醒等待线程中的一个
	cv_syn.wait(lck);
    }
}

// 线程C
void threadC(int id)
{
    while (1)
    {
        std::unique_lock<std::mutex> lck(mtx_syn);
        while (!ready) cv_syn.wait(lck);
        // ...
        std::cout << "threadC " << id << '\n';
        usleep(500*1000);
        cv_syn.notify_one();  // 唤醒等待线程中的一个线程
        cv_syn.wait(lck);
    }
}


void go()
{
    std::unique_lock<std::mutex> lck(mtx_syn);
    ready = true;
    //cv_syn.notify_one(); // 唤醒等待线程中的一个线程,notify_one()唤醒的线程顺序执行
    cv_syn.notify_all();  //唤醒的线程抢占式知性
}

int main()
{
    //线程同步
    std::thread threads[5];
    threads[0] = std::thread(threadA, 0);
    threads[1] = std::thread(threadB, 1);
    threads[2] = std::thread(threadC, 2);
    std::cout << "3 threads ready to race...\n";
    go();                       // go!

    for (auto& th : threads) th.join();
}

g++ main.cpp -o main -std=c++11 -lpthread

### 使用 C++ 进行 PostgreSQL 数据库通知 在 C++ 中使用 PostgreSQL 的通知机制涉及通过 `libpq` 库连接到数据库并监听特定通道上的通知消息。以下是实现这一功能的具体方法: #### 安装依赖项 为了能够在 C++ 程序中访问 PostgreSQL 数据库,需要安装 `libpq-dev` 包。该包提供了必要的头文件和静态链接库来编译应用程序。 ```bash sudo apt-get install libpq-dev ``` 此操作会安装 PostgreSQL 开发所需的组件,包括用于构建客户端应用的接口函数[^1]。 #### 编写 C++ 代码以发送和接收通知 下面是一个简单的例子展示怎样利用 C++ 发送以及捕获来自服务器端的通知事件。 ##### 发送通知 要向其他正在等待相同频道名的所有进程广播一条消息,可以执行 SQL 命令 `NOTIFY channel_name, 'payload';`. ```cpp #include <iostream> #include <libpq-fe.h> int main() { const char *conninfo = "dbname=mydb user=myuser password=mypassword hostaddr=127.0.0.1 port=5432"; PGconn* conn = PQconnectdb(conninfo); if (PQstatus(conn) != CONNECTION_OK){ std::cerr << "Connection to database failed." << std::endl; return -1; } // Send notification with payload std::string query = "NOTIFY my_channel, 'Hello from C++';"; PGresult* res = PQexec(conn, query.c_str()); if(PQresultStatus(res) != PGRES_COMMAND_OK){ std::cerr << "Sending NOTIFY command failed."; PQclear(res); PQfinish(conn); return -1; } PQclear(res); PQfinish(conn); } ``` ##### 接收通知 对于想要接收到这些异步更新的应用程序来说,则需调用 `PQsetnonblocking()` 设置非阻塞模式,并定期轮询是否有新的通知到达;也可以采用多线程的方式,在单独的工作线程里持续监视网络套接字的状态变化。 ```cpp void listen_for_notifications(PGconn* conn){ int sock = PQsocket(conn); fd_set rfds; while(true){ FD_ZERO(&rfds); FD_SET(sock,&rfds); struct timeval timeout={1,0}; // Wait up to one second. select(FD_SETSIZE, &rfds, NULL, NULL, &timeout ); if(!FD_ISSET(sock,&rfds)) continue; // Check for notifications after socket activity detected unsigned int notifies_count = PQnotifies(conn)!=NULL ? true : false ; if(notifies_count>0){ PGnotify *notify=PQnotifies(conn); printf("Received Notification: Channel=%s Payload='%s'\n", notify->relname , notify->extra ); free(notify); }else{ usleep(100000); // Sleep briefly before checking again. } } } // In your main function or another thread... listen_for_notifications(conn); ``` 上述代码片段展示了如何设置一个无限循环去检测是否有新到来的通知,并打印出相应的渠道名称及其携带的数据负载信息.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值