mirror of
https://github.com/CnTransGroup/EffectiveModernCppChinese.git
synced 2024-12-25 20:30:21 +08:00
parent
fa293eec23
commit
2fc6b628a9
@ -1,7 +1,7 @@
|
||||
## 条款十六:让`const`成员函数线程安全
|
||||
**Item 16: Make `const` member functions thread safe**
|
||||
|
||||
如果我们在数学领域中工作,我们就会发现用一个类表示多项式是很方便的。在这个类中,使用一个函数来计算多项式的根是很有用的,也就是多项式的值为零的时候。这样的一个函数它不会更改多项式。所以,它自然被声明为`const`函数。
|
||||
如果我们在数学领域中工作,我们就会发现用一个类表示多项式是很方便的。在这个类中,使用一个函数来计算多项式的根是很有用的,也就是多项式的值为零的时候(译者注:通常也被叫做零点,即使得多项式值为零的那些取值)。这样的一个函数它不会更改多项式。所以,它自然被声明为`const`函数。
|
||||
|
||||
```c++
|
||||
class Polynomial {
|
||||
@ -81,7 +81,7 @@ private:
|
||||
|
||||
`std::mutex m`被声明为`mutable`,因为锁定和解锁它的都是non-`const`成员函数。在`roots`(`const`成员函数)中,`m`却被视为`const`对象。
|
||||
|
||||
值得注意的是,因为`std::mutex`是一种只可移动类型(*move-only type*,一种可以移动但不能复制的类型),所以将`m`添加进`Polynomial`中的副作用是使`Polynomial`失去了被复制的能力。不过,它仍然可以移动。
|
||||
~~值得注意的是,因为`std::mutex`是一种只可移动类型(*move-only type*,一种可以移动但不能复制的类型),所以将`m`添加进`Polynomial`中的副作用是使`Polynomial`失去了被复制的能力。不过,它仍然可以移动。~~ (译者注:实际上 `std::mutex` 既不可移动,也不可复制。因而包含他们的类也同时是不可移动和不可复制的。)
|
||||
|
||||
在某些情况下,互斥量的副作用显会得过大。例如,如果你所做的只是计算成员函数被调用了多少次,使用`std::atomic` 修饰的计数器(保证其他线程视它的操作为不可分割的整体,参见[item40](../7.TheConcurrencyAPI/item40.md))通常会是一个开销更小的方法。(然而它是否轻量取决于你使用的硬件和标准库中互斥量的实现。)以下是如何使用`std::atomic`来统计调用次数。
|
||||
|
||||
@ -102,7 +102,7 @@ private:
|
||||
};
|
||||
```
|
||||
|
||||
与`std::mutex`一样,`std::atomic`是只可移动类型,所以在`Point`中存在`callCount`就意味着`Point`也是只可移动的。
|
||||
~~与`std::mutex`一样,`std::atomic`是只可移动类型,所以在`Point`中存在`callCount`就意味着`Point`也是只可移动的。~~(译者注:与 `std::mutex` 类似的,实际上 `std::atomic` 既不可移动,也不可复制。因而包含他们的类也同时是不可移动和不可复制的。)
|
||||
|
||||
因为对`std::atomic`变量的操作通常比互斥量的获取和释放的消耗更小,所以你可能会过度倾向与依赖`std::atomic`。例如,在一个类中,缓存一个开销昂贵的`int`,你就会尝试使用一对`std::atomic`变量而不是互斥量。
|
||||
|
||||
@ -187,7 +187,7 @@ private:
|
||||
|
||||
```
|
||||
|
||||
现在,这个条款是基于,多个线程可以同时在一个对象上执行一个`const`成员函数这个假设的。如果你不是在这种情况下编写一个`const`成员函数——你可以**保证**在一个对象上永远不会有多个线程执行该成员函数——该函数的线程安全是无关紧要的。比如,为独占单线程使用而设计的类的成员函数是否线程安全并不重要。在这种情况下,你可以避免因使用互斥量和`std::atomics`所消耗的资源,以及包含它们的类只能使用移动语义带来的副作用。然而,这种线程无关的情况越来越少见,而且很可能会越来越少。可以肯定的是,`const`成员函数应支持并发执行,这就是为什么你应该确保`const`成员函数是线程安全的。
|
||||
现在,这个条款是基于,多个线程可以同时在一个对象上执行一个`const`成员函数这个假设的。如果你不是在这种情况下编写一个`const`成员函数——你可以**保证**在一个对象上永远不会有多个线程执行该成员函数——该函数的线程安全是无关紧要的。比如,为独占单线程使用而设计的类的成员函数是否线程安全并不重要。在这种情况下,你可以避免因使用互斥量和`std::atomics`所消耗的资源,以及包含它们的类~~只能使用移动语义~~(译者注:既不能移动也不能复制)带来的副作用。然而,这种线程无关的情况越来越少见,而且很可能会越来越少。可以肯定的是,`const`成员函数应支持并发执行,这就是为什么你应该确保`const`成员函数是线程安全的。
|
||||
|
||||
**请记住:**
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user