C++;:Linux平台上的线程同步方案 我在Linux平台上实现了多线程C++程序,在这里我需要一个类似于WaTimeTyrPultObjultSo()的功能。p>

C++;:Linux平台上的线程同步方案 我在Linux平台上实现了多线程C++程序,在这里我需要一个类似于WaTimeTyrPultObjultSo()的功能。p>,c++,linux,multithreading,synchronization,C++,Linux,Multithreading,Synchronization,在搜索解决方案时,我注意到有一些文章通过示例描述了如何在Linux中实现WaitForMultipleObjects()功能,但这些示例并不满足我必须支持的场景 我的情况非常简单。我有一个守护进程,在这个进程中,主线程向外界公开一个方法/回调,例如DLL。DLL的代码不在我的控制之下。同一主线程创建一个新线程“thread1”。线程1必须执行一种无限循环,在这种循环中它将等待关闭事件(守护进程关闭),或者它将等待通过上述公开方法/回调发出信号的数据可用事件 简言之,线程将等待shutdown事件

在搜索解决方案时,我注意到有一些文章通过示例描述了如何在Linux中实现WaitForMultipleObjects()功能,但这些示例并不满足我必须支持的场景

我的情况非常简单。我有一个守护进程,在这个进程中,主线程向外界公开一个方法/回调,例如DLL。DLL的代码不在我的控制之下。同一主线程创建一个新线程“thread1”。线程1必须执行一种无限循环,在这种循环中它将等待关闭事件(守护进程关闭),或者它将等待通过上述公开方法/回调发出信号的数据可用事件

简言之,线程将等待shutdown事件和data available事件,如果向shutdown事件发出信号,等待将满足,循环将被中断,或者如果向data available事件发出信号,那么等待也将满足,线程将进行业务处理

在windows中,它看起来非常直接。下面是我的场景中基于MS Windows的伪代码

//**Main thread**

//Load the DLL
LoadLibrary("some DLL")

//Create a new thread
hThread1 = __beginthreadex(..., &ThreadProc, ...)

//callback in main thread (mentioned in above description) which would be called by the     DLL
void Callbackfunc(data)
{
    qdata.push(data);
    SetEvent(s_hDataAvailableEvent);
}

void OnShutdown()
{
    SetEvent(g_hShutdownEvent);
    WaitforSingleObject(hThread1,..., INFINITE);
    //Cleanup here
}

//**Thread 1**

unsigned int WINAPI ThreadProc(void *pObject)
{
    while (true)
    {

        HANDLE hEvents[2];
        hEvents[0] = g_hShutdownEvent;
        hEvents[1] = s_hDataAvailableEvent;

        //3rd parameter is set to FALSE that means the wait should satisfy if state of  any one of the objects is signaled.
        dwEvent = WaitForMultipleObjects(2, hEvents, FALSE, INFINITE);
        switch (dwEvent) 
        {   
            case WAIT_OBJECT_0 + 0: 
            // Shutdown event is set, break the loop
            return 0;   

            case WAIT_OBJECT_0 + 1:
            //do business processing here
            break; 

            default: 
            // error handling
        }
    }
}

我想在Linux上实现同样的功能。根据我对Linux的理解,它有完全不同的机制,我们需要注册信号。如果终止信号到达,进程将知道它即将关闭,但在此之前,进程必须等待正在运行的线程正常关闭。

在Linux中执行此操作的正确方法是使用条件变量。虽然这与Windows中的WaitForMultipleObjects不同,但您将获得相同的功能

使用两个
bool
s来确定是否有可用数据或必须关闭。 然后让关机功能和数据功能都相应地设置布尔值,并向条件变量发送信号

#include <pthread.h>

pthread_cond_t cv = PTHREAD_COND_INITIALIZER;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

pthread_t hThread1; // this isn't a good name for it in linux, you'd be 
                    // better with something line "tid1" but for 
                    // comparison's sake, I've kept this

bool shutdown_signalled;
bool data_available;

void OnShutdown()
{
    //...shutdown behavior...
    pthread_mutex_lock(&mutex);
    shutdown_signalled = true;
    pthread_mutex_unlock(&mutex);
    pthread_cond_signal(&cv);
}

void Callbackfunc(...)
{
    // ... whatever needs to be done ...
    pthread_mutex_lock(&mutex);
    data_available = true;
    pthread_mutex_unlock(&mutex);
    pthread_cond_signal(&cv);
}


void *ThreadProc(void *args)
{
    while(true){
        pthread_mutex_lock(&mutex);
        while (!(shutdown_signalled || data_available)){
            // wait as long as there is no data available and a shutdown
            // has not beeen signalled
            pthread_cond_wait(&cv, &mutex);
        }
        if (data_available){
            //process data
            data_available = false;
        }
        if (shutdown_signalled){
            //do the shutdown
            pthread_mutex_unlock(&mutex);
            return NULL;
        }
        pthread_mutex_unlock(&mutex); //you might be able to put the unlock
        // before the ifs, idk the particulars of your code
    }
}
int main(void)
{
    shutdown_signalled = false;
    data_available = false;
    pthread_create(&hThread1, &ThreadProc, ...);
    pthread_join(hThread1, NULL);
    //...
}
#包括
pthread_cond_t cv=pthread_cond_初始值设定项;
pthread\u mutex\u t mutex=pthread\u mutex\u初始值设定项;
pthread_t hThread1;//这在linux中不是一个好名字,你可能会是
//最好在“tid1”行加上一些东西
//看在比较的份上,我留着这个
发出bool关闭信号;
bool数据可用;
void OnShutdown()
{
//…关机行为。。。
pthread_mutex_lock(&mutex);
关闭信号=真;
pthread_mutex_unlock(&mutex);
pthread_cond_信号(&cv);
}
void Callbackfunc(…)
{
//…无论需要做什么。。。
pthread_mutex_lock(&mutex);
可用数据=真;
pthread_mutex_unlock(&mutex);
pthread_cond_信号(&cv);
}
void*ThreadProc(void*args)
{
while(true){
pthread_mutex_lock(&mutex);
而(!(停机信号| |数据|可用)){
//只要没有可用数据和关机,请等待
//还没有发出信号
pthread_cond_wait(&cv,&mutex);
}
如果(数据可用){
//过程数据
数据_可用=错误;
}
如果(有停机信号){
//停止工作吗
pthread_mutex_unlock(&mutex);
返回NULL;
}
pthread_mutex_unlock(&mutex);//您可以将解锁
//在国际单项体育联合会之前,请输入您的代码详情
}
}
内部主(空)
{
停机信号=错误;
数据_可用=错误;
pthread_create(&hThread1,&ThreadProc,…);
pthread_join(hThread1,NULL);
//...
}

我知道windows也有条件变量,所以这看起来不太陌生。我不知道windows有什么规则,但在POSIX平台上,
wait
需要在
while
循环中,因为可能会发生“虚假唤醒”。

如果您希望编写unix或linux特定的代码,您可以使用不同的API:

  • pthread:提供线程、互斥、条件变量
  • IPC(进程间通信)机制:互斥、信号量、共享内存
  • 信号
对于线程,第一个库是必需的(linux上有较低级别的系统调用,但它更繁琐)。对于事件,可以使用三个

系统关闭事件生成终止(SIG_TERM)和终止(SIG_kill)信号,并广播到所有相关进程。因此,也可以通过这种方式启动单个守护进程关闭。游戏的目标是捕捉信号,并启动进程关闭。重点是:

  • 信号机制的构造方式使得无需等待它们

    只需使用
    sigaction
    安装一个所谓的处理程序,系统就会完成其余的工作

  • 信号被设置为进程,任何线程都可以拦截它(处理程序可以在任何上下文中执行)

    因此,您需要安装一个信号处理程序(请参阅),并以某种方式将信息传递给应用程序必须终止的其他线程

最方便的方法可能是使用一个全局互斥保护标志,所有线程都会定期查看该标志。信号处理程序将设置该标志以指示关机。对于工作线程,它意味着

  • 告诉远程主机服务器正在关闭
  • 读取时关闭其套接字
  • 处理所有剩余的接收命令/数据并发送应答
  • 合上插座
  • 出口
对于主线程,这意味着在工作线程上启动联接,然后退出

此模型不应干扰数据的正常处理方式:如果捕获到信号,则对
select
poll
的阻塞调用将返回错误
EINTR
,对于非阻塞调用,线程将被重新调用