Table of Contents
1 STL, Thread and SGI
C++98 以及以前的 C++ 標準中,並未對線程作出過規定,但對於 STL 來說,SGI 作出了本身的規定,不少其餘的 STL 實現也遵循這些規定:html
The SGI implementation of STL is thread-safe only in the sense that simultaneous accesses to distinct containers are safe, and simultaneous read accesses to to shared containers are safe. If multiple threads access a single container, and at least one thread may potentially write, then the user is responsible for ensuring mutual exclusion between the threads during the container accesses.java
This is the only way to ensure full performance for containers that do not need concurrent access. Locking or other forms of synchronization are typically expensive and should be avoided when not necessary.c++
It is easy for the client or another library to provide the necessary locking by wrapping the underlying container operations with a lock acquisition and release. For example, it would be possible to provide a locked_queue container adapter that provided a container with atomic queue operations.sql
For most clients, it would be insufficient to simply make container operations atomic; larger grain atomic actions are needed. If a user's code needs to increment the third element in a vector of counters, it would be insuffcient to guarantee that fetching the third element and storing the third element is atomic; it is also necessary to guarantee that no other updates occur in the middle. Thus it would be useless for vector operations to acquire the lock; the user code must provide for locking in any case.bash
This decision is different from that made by the Java designers. There are two reasons for that. First, for security reasons Java must guarantee that even in the presence of unprotected concurrent accesses to a container, the integrity of the virtual machine cannot be violated. Such safety constraints were clearly not a driving force behind either C++ or STL. Secondly, performance was a more important design goal for STL than it was for the Java standard library.app
On the other hand, this notion of thread-safety is stronger than that provided by reference-counted string implementations that try to follow the CD2 version of the draft standard. Such implementations require locking between multiple readers of a shared string.less
2 STL and Lock
2.1 RAII
須要對一個容器進行寫操做的時候,咱們能夠加鎖保護:ide
1: // skeletal template for classes that acquire and release mutexes for containers; many 2: // details have been omitted 3: template<typename Container> class Lock 4: { 5: public: 6: Lock(const Containers container) : c(container) 7: { 8: getMutexFor(c); // Acquire mutex in constructor 9: } 10: ~Lock() 11: { 12: releaseMutexFor(c); // Release mutex in constructor 13: } 14: private: 15: const Container& c; 16: };
這裏用到了一個技巧 Resource Acquisition Is Initialization ( RAIII ) ,其基本思想包括:post
- 所用資源在對象構造時就初始化好
這樣能夠保證用到該對象時,所需訪問的資源始終爲 Valid 狀態。 - 所用資源在對象析構時釋放
這樣就保證了資源能夠自動釋放。
2.2 Use Lock in STL
17: vector<int>v; 18: { 19: Lock<vector<int> > lock(v); // Lock initialized here. 20: vector<int>::iterator frist5(find(v.begin(), v.end(), 5)); 21: if (first5 != v.end()) 22: { 23: *first5 = 0; 24: } 25: } // Lock will be released after exit this scope.