QThread
create
{
QThread * th = Q_NULLPTR;
' create会自动给创建线程, 你获得他的所有权!! 即, 你负责他的delete '
th = QThread::create( GET_ADDRESS_( thread_func));
connect( th, &QThread::started, this, [](){
' 说明, 此时已经进入thread_func()函数 开始执行了 '
});
connect( th, &QThread::finished, this, [ th](){
' 说明此时, 已经执行完thread_func()函数了 '
th->deleteLater();
});
th->start(); ' 调用start()之后, 才会 开始执行func, 即发出started信号 '
}
QMutex
用法和 std::mutex
一样, 也是: lock(), unlock(), try_lock()
三个核心函数
QReadWriteLock
他是有: lockForRead() lockForWrite(), unlock()
, 他也是遵循: 一个lock (ForRead 或 ForWrite), 必须对应一个 unlock()
他和QMutex有类似的地方;
- (mutex是: 比如有
a, b, c
三个线程 竞争这个mutex)
如果mutex上锁了, 必然, 此时此刻, 只有 一个线程 获取了这个mutex; 其他两个线程 都是blocked的 - 但ReadWriteLock
读写锁
, 比如a, b, c, d
四个线程 (且ab是读lockForRead
, cd是写lockForWrite
)
所有的 (读 线程), 是可以 同时进行的;读写锁的内部, 有3个状态: 空闲, 读, 写;
且会有一个read_count, 表示 目前在同时进行读的线程个数; 当为(读)状态时, read_count 肯定 > 0
读写锁, 初始是: (空闲, read_count = 0);- 当调用
lockForRead()
时:- 如果当前读写锁的状态是: (空闲), 则: 获得锁
即, 可以执行代码
, 且将(读写锁状态, 设置为: 读) (read_count ++) - 如果当前读写锁的状态是: (读), 则: 获得锁
即, 可以执行代码
, 且将(读写锁状态, 设置为: 读) (read_count ++) - 如果当前读写锁的状态是: (写), 则: blocked
等价于: mutex.lock()的堵塞
, 等待, 直到: 读写锁状态 不是 (写)
- 如果当前读写锁的状态是: (空闲), 则: 获得锁
- 当调用
lockForWrite()
时:- 如果当前读写锁的状态是: (空闲), 则: 获得锁
即, 可以执行代码
, 且将(读写锁状态, 设置为: 写) - 如果当前读写锁的状态是: (读) 或 (写), 则: blocked
等价于: mutex.lock()的堵塞
, 等待, 直到: 读写锁状态 变为 (空闲)
- 如果当前读写锁的状态是: (空闲), 则: 获得锁
- 当调用
unlock()
时:- 如果当前读写锁的状态是: (写), 则: 将读写锁状态 变为: (空闲)
- 如果当前读写锁的状态是: (读), 则:
-- read_count
; (如果更新后,read_count == 0
则读写锁状态变为 (空闲); 否则> 0
, 状态仍为 (读)
- 当调用
简而言之, 当读写锁 是 上锁状态时, 有 两种情况
- 要么, 有 若干个 线程, (同时), 在进行 (读操作)
我们知道, 进行读操作, 也就是, const对象, 是 线程安全的!!
- 要么, 只有 一个 线程, 在进行 (写操作)
QReadLocker, QWriteLocker
对于读写锁, (一次 lockForRead()
, 必须对应 一次unlock()
), (一次 lockForWrite()
, 必须对应 一次unlock()
)
就和, QMutex是一样的 (一次lock()
, 必须对应一次unlock()
)
为了防止你忘记, QMutex 引入了 QMutexLocker
(帮助你, 在构造函数lock, 在析构unlock)
同样, QReadWriteLock 引入了 QReadLocker 和 QWriteLocker
(帮助你, 在构造函数调用lockForRead/ Write
, 在析构调用unlock
)