Qt,关于UDPlink的线程安全

Qt, thread safety regarding UDPlink

本文关键字:线程 安全 UDPlink 关于 Qt      更新时间:2023-10-16

如果我有一个Qt的UDPlink和一个像这样的writeBytes函数:

void UDPLink::writeBytes(const char* data, qint64 size)
{
    // Broadcast to all connected systems
    for (int h = 0; h < hosts.size(); h++)
    {
        QHostAddress currentHost = hosts.at(h);
        quint16 currentPort = ports.at(h);
        socket->writeDatagram(data, size, currentHost, currentPort);
    }
}

这里的套接字是一个 UDP 套接字。此函数线程安全吗?也就是说我可以从 2 个不同的线程调用 writeBytes() 函数吗?

唯一可能不是螺纹安全的 2 个部分:

一个是数据报可能会交错(无论如何都会在UDP中发生,所以不用担心)

另一件事是QUdpSocket::writeDatagram不是线程安全的。因此,您要么需要将套接字的访问与互斥锁同步,要么使用信号/插槽,或者为每个线程创建一个套接字。

使其线程安全很容易:

//make it a slot or invokable
void UDPLink::writeBytes(const char* data, qint64 size)
{
    if(QThread::currentThread() != thread())
    {
        QByteArray buff(data, size);//makes a copy pass in a QByteArray to avoid
        QMetaObject::invokeMethod(this, "writeBytes", Q_ARG(QByteArray, buff));
        //this forward the call to the thread that this object resides in if the calling thread is different.
        return;
    }
    for (int h = 0; h < hosts.size(); h++)
    {
        QHostAddress currentHost = hosts.at(h);
        quint16 currentPort = ports.at(h);
        socket->writeDatagram(data, size, currentHost, currentPort);
    }
}

答案是否定的,QUDPsocket不是线程安全的,而是可重入的,这意味着您不能使用相同的实例从2个不同的线程调用QUDPSocket->writeDatagram/writeBytes,您可以从QUDPSocket的单独实例调用调用QUDPSocket->writeDatagram/writeBytes