16.3.2  lock模板类

16.3.2 lock模板类

锁是一种互斥对象,其确保可锁定性对象的引用,并解锁可锁定性对象。可执行程序(或线程)可以使用一个锁,以帮助管理可锁定性对象的占有权。锁通常可以占有可锁定性对象,但不能管理可锁定对象的终个寿命期。一些锁的构造函数具有附加参数,在锁对象存续期间,这些附加参数可以处理可锁定对象。

本小节主要讲述两种互斥锁:lock_guard和unique_lock。

1.lock_guard

lock_guard模板类的声明形式如下:

978-7-111-51399-5-Chapter16-38.jpg

lock_guard模板类包含两个构造函数,这两个构造函数不能复制、不能移动,且不能使用赋值符号。

lock_guard类型对象可以控制可锁定对象的占有权,使其在占有权在某范围内有效。lock_guard对象确保可锁定对象的占有权贯穿lock_guard类型对象的整个生命期。lock_guard和mutex类对象配合使用,一旦将锁放进lock_guard中(作为lock_guard构造函数的参数),mutex自动加锁;lock_guard析构时,互斥类型对象mutex自动解锁。由此可知,lock_guard类型对象是自动加锁和自动解锁的。lock_guard是最简单的加锁、解锁办法。

lock_guard模板类包含两种形式的构造函数:

978-7-111-51399-5-Chapter16-39.jpg

其中,第一种形式是自动加锁;第二种形式包含两个参数,第二个参数代表采用第一个参数指定的锁对象。lock_guard模板类的具体使用方法详见例16-8。

例16-8

978-7-111-51399-5-Chapter16-40.jpg

978-7-111-51399-5-Chapter16-41.jpg

例16-8的执行效果如图16-8所示。

978-7-111-51399-5-Chapter16-42.jpg

图16-8 例16-8的执行效果

2.unique_lock模板类

unique_lock模板类的声明形式如下:

978-7-111-51399-5-Chapter16-43.jpg

978-7-111-51399-5-Chapter16-44.jpg

unique_lock模板类具有多个构造函数,因此其使用形式也是多样的。此外,该模板类还具有一个有效的赋值符号。和其他锁对象不同,unique_guard还拥有owns_lock()、release()等函数。

其常用的构造函数(即常用的使用方法)包含以下几种:

978-7-111-51399-5-Chapter16-45.jpg

其中涉及3个参数:defer_lock_t、try_to_lock和adopt_lock_t。其意义分别如下:

•defer_lock。不在构造器中对互斥量加锁,假定该互斥量在线程中加锁。

•try_lock。通过调用成员函数try_lock在构造器中加锁。

•adopt_lock。采用当前的互斥量(锁),假定其在线程中加锁。

参数abs_time代表绝对时间(时刻),而参数rel_time代表相对时间。

类的加锁和解锁是通过成员函数lock、try_lock、try_lock_until、try_lock_for和unlock实现的。成员函数swap、release可以用于unique_guard对象。其中release()函数将unique_guard类对象管理的所有互斥锁全部释放,并返回该互斥锁的指针;mutex()函数将获取当前的互斥锁;owns_lock()函数用于判断互斥锁是否被锁定。

值得注意的是,由于unique_lock模板类具有的多种构造函数以及诸多成员函数,因此在定义其对象时,要注意模板中参数classMutex的替换,详见例16-9。

978-7-111-51399-5-Chapter16-46.jpg

例16-9

978-7-111-51399-5-Chapter16-47.jpg

978-7-111-51399-5-Chapter16-48.jpg

978-7-111-51399-5-Chapter16-49.jpg

例16-9的执行效果如图16-9所示。

978-7-111-51399-5-Chapter16-50.jpg

图16-9 例16-9的执行效果