Изменения
→mutexes (mutex, recuirsive_mutex, shared_mutex)
Если в данном коде использовать обычный mutex, то программа зависнет (получит deadlock), так как f1 не сможет взять lock и будет ждать. При использовании recursive_mutex все будет нормально (поскольку к объекту обращаются с одного и того же треда, f1 сможет взять lock). Снимать lock нужно столько же раз, сколько и брать, иначе другие потоки не смогут работать с данными.
shared_mutex - boost'овая хрень. Читать тут: [http://stackoverflow.com/questions/989795/example-for-boost-shared-mutex-multiple-reads-one-write/4820461#4820461]. Видимо смысл в том, что в обычных мютексах мы не могли читать одновременно из двух потоков, т.к. нужно было взять lock (вдруг кто-то третий начнет изменять данные). А тут можно.
=== condition_variable ===