对线程处理很陌生,我有线程之间共享的这个 QList。他们都有自己的工作空间,GUI(模型/ View )不断访问这个列表。然后我得到这个指向 QDataList.size() 的崩溃。调试并没有真正帮助我,因为如果我单步执行代码并且当我尝试崩溃的 qList 时,我从来没有遇到过这个问题,没有可用的信息。
所以,我的问题是:是否可以同时获取 Qlists 大小和读取对象?列表中的对象是线程安全的,不能同时被不同的线程读/写。
获取“0xC0000005:读取位置 0xfeeefefa 的访问冲突。”这让我想到: qlist.h 中的 inline int size() const
我遍历了调用堆栈,发现了这个:
QtCored4.dll!QListData::size() Line 98 + 0x11 bytes C++
QtNetworkd4.dll!QList<enum QNetworkReplyImplPrivate::InternalNotifications>::size() Line 137 + 0x10 bytes C++
QtNetworkd4.dll!QNetworkReplyImplPrivate::resumeNotificationHandling() Line 444 + 0xe bytes C++
QtNetworkd4.dll!QNetworkReplyImplPrivate::finished() Line 797 C++
QtNetworkd4.dll!QNetworkAccessBackend::finished() Line 313 C++
QtNetworkd4.dll!QNetworkAccessHttpBackend::replyFinished() Line 739 C++
QtNetworkd4.dll!QNetworkAccessHttpBackend::qt_static_metacall(QObject * _o, QMetaObject::Call _c, int _id, void * * _a) Line 86 + 0x8 bytes C++
QtCored4.dll!QMetaCallEvent::placeMetaCall(QObject * object) Line 525 + 0x1d bytes C++
QtCored4.dll!QObject::event(QEvent * e) Line 1195 + 0x14 bytes C++
QtGuid4.dll!QApplicationPrivate::notify_helper(QObject * receiver, QEvent * e) Line 4550 + 0x11 bytes C++
QtGuid4.dll!QApplication::notify(QObject * receiver, QEvent * e) Line 3932 + 0x10 bytes C++
QtCored4.dll!QCoreApplication::notifyInternal(QObject * receiver, QEvent * event) Line 876 + 0x15 bytes C++
QtCored4.dll!QCoreApplication::sendEvent(QObject * receiver, QEvent * event) Line 231 + 0x39 bytes C++
QtCored4.dll!QCoreApplicationPrivate::sendPostedEvents(QObject * receiver, int event_type, QThreadData * data) Line 1500 + 0xd bytes C++
QtCored4.dll!qt_internal_proc(HWND__ * hwnd, unsigned int message, unsigned int wp, long lp) Line 496 + 0x10 bytes C++
每个线程都有一个执行网络请求的网络管理器:
QThread ASSERT failure in QMutexLocker: "QMutex pointer is misaligned",
最佳答案
我意识到可以预先分配一个 QList 并让线程对该列表的不同区域进行操作,但在我看来,我认为这是一个不好的模式。
当我使用 Qt 时(我实际上使用 PyQt,因为我是一名 Python 程序员),我觉得最好使用提供给您的信号/槽机制并且从不在线程之间共享内存。每个线程都应该在创建时直接获得自己的数据,或者随着时间的推移通过等待的队列获得。当它完成它的工作或一大块工作时,它可以发出一个带有数据的信号。您将拥有一个连接到所有线程的处理程序,以监听准备就绪的数据。
这种模式的结果是你没有共享内存,你不必太担心锁,而只是等待工作人员发出数据准备就绪的信号,并且单个处理程序正在收集和更新主要模型。
话虽这么说,这里是另一个引用资料,有人将 QList 用作共享内存并在锁定它之前遇到崩溃:http://developer.qt.nokia.com/forums/viewthread/13049
我认为当人们(包括我自己)第一次开始使用线程时,直接的冲动就是像他们一直那样使用容器。但是一旦开始线程化,代码逻辑的复杂性以及错误的容量就会立即增加。共享内存的同步是一种方法,在访问之前使用互斥体锁定资源。但我认为值得一提的是另一种沟通方式。
Google 的 Go 语言是根据其核心原则之一构建的:“不要通过共享内存进行通信;通过通信共享内存”http://golang.org/doc/codewalk/sharemem/
Go 希望通过 channel 对象(类似于 Qt 中的信号/槽)通信内存来解决这个问题的核心。一个组件具有对内存的独占本地访问权限,然后通过 channel 将其传递给另一个组件。这保证你不会有竞争条件。无论如何,我只是认为我会添加这个额外的引用,因为我觉得它与线程编程问题非常相关。
关于c++ - 两个线程可以同时读取同一个QList吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9476045/