[英]Should mutex be used when inserting element in vectors?
我知道在嘗試從向量中刪除元素時需要互斥量。
所以,我寫了一個示例代碼來檢查這個。
class Test
{
public:
Test(int idx) : m_index(idx) {}
int m_index = { -1 };
int m_count = { 0 };
};
std::vector<std::unique_ptr<Test>> m_vec;
std::mutex m_mutex;
void foo1() // print element data
{
while (true)
{
std::unique_lock ulock(m_mutex);
for (auto& e : m_vec)
{
e->m_count++;
printf("%d : Count : %d\n", e->m_index, e->m_count);
}
ulock.unlock();
std::this_thread::sleep_for(std::chrono::milliseconds(5));
}
}
void foo2() // Only insert element
{
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_int_distribution<int> dis(0, 99);
while (true)
{
int t = dis(gen);
if (t >= 0 && t < 10)
{
//std::unique_lock ulock(m_mutex);
m_vec.push_back(std::make_unique<Test>(m_vec.size()));
}
std::this_thread::sleep_for(std::chrono::milliseconds(t));
}
}
void foo3() // Only remove element
{
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_int_distribution<int> dis(0, 99);
while (true)
{
int t = dis(gen);
if (t >= 0 && t < 10)
{
std::unique_lock ulock(m_mutex);
if (m_vec.empty() == false)
m_vec.erase(m_vec.begin());
}
std::this_thread::sleep_for(std::chrono::milliseconds(t));
}
}
int main()
{
m_vec.push_back(std::make_unique<Test>(1));
m_vec.push_back(std::make_unique<Test>(2));
m_vec.push_back(std::make_unique<Test>(3));
std::thread t1(foo1);
std::thread t2(foo2);
std::thread t3(foo3);
t1.join();
t2.join();
t3.join();
return 0;
}
如果我在不使用互斥量的情況下繼續使用 erase(),幾乎會立即發生段錯誤。
所以我對 erase() 例程使用了互斥量,它似乎工作正常。
然而,大約 10 分鍾后,在 foo1() function 中引用 e 時發生 nullptr 異常。
Q1。 push_back在末尾插入數據。 但是為什么在中間點會出現NULL錯誤呢? 前任。 矢量大小:521,錯誤索引:129)
Q2。 使用 vector 和 deque 等有序容器時,插入函數中是否需要互斥量?
Q3。 無序容器呢? (比如,unorderd_map)(從 insert 中移除 mutex 並運行大約 20 分鍾沒有任何問題。)
foo2()
正在訪問/修改mutex
鎖之外的vector
。 因此, foo1()
和/或foo3()
(確實使用mutex
)能夠與foo2()
同時修改vector
。 那是未定義的行為。
push_back最后插入數據時,為什么會出現中間點(ex. vector size: 521, error index: 129)Null點錯誤?
將新元素推入vector
可能需要它重新分配其內部數組,從而將所有現有元素移動到新的 memory 塊。 您在沒有mutex
鎖保護的情況下在foo2()
中執行此操作,因此foo1()
和foo3()
正在訪問的元素可能會意外消失。
從vector
中擦除元素不會重新分配內部數組,但它仍可能會在數組現有的 memory 內移動元素。
使用 vector 和 deque 等有序容器時,插入和刪除函數中是否需要互斥量?
是的。 所有標准容器都不是線程安全的,因此在跨線程邊界使用時必須對修改進行序列化。
無序容器呢? (比如,unorderd_map)(從 insert 中移除 mutex 並運行大約 20 分鍾沒有任何問題。)
一樣。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.