1# 线程安全map 2 3## 概述 4 5### 简介 6提供了一个线程安全的map实现。SafeMap在STL map基础上封装互斥锁,以确保对map的操作安全。 7 8## 涉及功能 9### class SafeMap 10#### 接口说明 11 12 13|返回类型 |名称 | 14| -------------- | -------------- | 15| | **SafeMap**() | 16| | **SafeMap**(const SafeMap& rhs) | 17| | **~SafeMap**() | 18| void | **Clear**()<br>删除map中存储的所有键值对。 | 19| void | **EnsureInsert**(const K& key, const V& value)<br>在map中插入元素。 | 20| void | **Erase**(const K& key)<br>删除map中键为key的键值对。 | 21| bool | **Find**(const K& key, V& value)<br>在map中查找元素。 | 22| bool | **FindOldAndSetNew**(const K& key, V& oldValue, const V& newValue)<br>在map中查找元素并将key对应的`oldValue`替换为`newValue`。 | 23| bool | **Insert**(const K& key, const V& value)<br>在map中插入新元素。 | 24| bool | **IsEmpty**()<br>判断map是否为空。 | 25| void | **Iterate**(const SafeMapCallBack& callback)<br>遍历map中的元素。 | 26| SafeMap& | **operator=**(const SafeMap& rhs) | 27| V | **ReadVal**(const K& key) <br> 线程安全地读map内元素| 28| void | **ChangeValueByLambda**(const K& key, LambdaCallback callback) <br> 线程安全地操作safemap内元素,操作行为需要自定义| 29| int | **Size**()<br>获取map的size大小。 | 30 31## 使用示例 32 331. 示例代码(伪代码) 34 35```c++ 36#include <thread> 37#include <iostream> 38#include <functional> 39#include "../include/safe_map.h" 40 41using namespace OHOS; 42using namespace std; 43 44constexpr int THREAD_NUM = 5; 45thread threads[THREAD_NUM * 2]; 46SafeMap<int, string> sm; 47 48bool InsertHandler(const int& key, const string& value) 49{ 50 if (sm.Insert(key,value)) { 51 cout << "Insert key: " << key << endl; 52 return true; 53 } else { 54 return false; 55 } 56} 57 58bool FindHandler(const int& key, string& value) 59{ 60 if (sm.Find(key,value)) { 61 cout << "Find key: " << key << " with value: " << value << endl; 62 return true; 63 } else { 64 return false; 65 } 66} 67 68 69int main() 70{ 71 for (int i = 0; i < THREAD_NUM; i++) { 72 string name = "Thread" + to_string(i); 73 threads[i] = thread(&InsertHandler, i, name); 74 } 75 76 for (int i = 0; i < THREAD_NUM; i++) { 77 string out; 78 threads[i + THREAD_NUM] = thread(&FindHandler, i, ref(out)); 79 } 80 81 this_thread::sleep_for(chrono::milliseconds(300)); 82 83 for (int i = 0; i < 2 * THREAD_NUM; i++) { 84 threads[i].join(); 85 } 86 87 88 if (sm.Size() == THREAD_NUM) { 89 cout << "Insert to SafeMap success!" << endl; 90 } 91} 92``` 93 942. 测试用例编译运行方法 95 96- 测试用例代码参见base/test/unittest/common/utils_safe_map_test.cpp 97 98- 使用开发者自测试框架,使用方法参见:[开发自测试执行框架-测试用例执行](https://gitee.com/openharmony/testfwk_developer_test#%E6%B5%8B%E8%AF%95%E7%94%A8%E4%BE%8B%E6%89%A7%E8%A1%8C) 99 100- 使用以下具体命令以运行`safe_map.h`对应测试用例 101 102```bash 103run -t UT -tp utils -ts UtilsSafeMapTest 104``` 105 1063. 接口使用变更 107 108- operator[]接口被废弃:该接口返回类型为引用,可以使用于读写场景,但在写场景情况下,该接口无法进行线程安全防护,因写行为本身基于引用由调用方触发,而非接口内部行为,接口内部持锁无法控制,因此失去线程安全的意义。 109 110```cpp 111SafeMap<int, string> sm; 112// Thread 1: 113sm[1] = "abc"; 114 115// Thread 2: 116sm[2] = "def"; 117``` 118 119- 提供专用的线程安全读接口:ReadVal,该接口只具有safemap的读取能力,但保证线程安全 120 121```cpp 122SafeMap<string, int> sm; 123// Thread 1: 124sm.Insert("A", 1); 125int val = sm.ReadVal("A"); 126``` 127 128- 针对之前利用operator[]返回引用进行的特殊元素操作行为,提供了接口ChangeValueByLambda进行替换,调用者自定义元素操作函数,可保证在线程安全的情况下操作safemap元素。 129 130```cpp 131SafeMap<string, std::set<int>> sm; 132int val = 1; 133auto fn = [&](std::set<int> &value) -> void { // 自定义callback 134 value.emplace(val); 135} 136sm.ChangeValueByLambda("A", fn); 137```