为什么 mutex 不适用于 2 个线程共享资源?
Why mutex is not working with 2 threads sharing resource?
我想测试一个场景,我检查 weak_ptr 有效性和 return shared_ptr。在检查和 returning 之间,如果其他线程删除了 shared_ptr,我们将面临异常。我尝试使用 windows sleep 或 cout 模拟相同的场景,但它似乎不起作用。代码如下:
#include <iostream>
#include <thread>
#include <windows.h>
#include <mutex>
using namespace std;
mutex m;
struct Block
{
int * p_ = nullptr;
Block() { p_ = new int[10000]; refCount_++; }
~Block() { delete[] p_; _p = nullptr; }
int refCount_;
};
struct Weak_ptr
{
Block * p_ = nullptr;
Weak_ptr() { p_ = new Block(); }
void Addref() { p_->refCount_++; }
void release() { delete[] p_; p_ = nullptr; cout << "\nptr deleted\n"; }
};
void funct1(int x, Weak_ptr *ptr)
{
cout << "\nin thread 1 \n";
cout << "\nSleep thread 1\n";
//Sleep(x)
for (int i = 0; i < x; i++)
cout << ".";
cout << "\nAwake thread 1\n";
ptr->release();
}
void funct2(int x, Weak_ptr *ptr)
{
m.lock();
cout << "\nin thread 2 \n";
if (ptr->p_)
{
cout << "\nptr checked \n";
//Sleep(x)
for (int i = 0; i < x; i++)
cout << "|";
cout << "\nusing ptr in t2\n";
ptr->Addref();
}
else
{
cout << "\ncheck succeeded \n";
}
m.unlock();
}
int main()
{
Weak_ptr s;
thread t1(&funct1, 2000, &s);
thread t2(&funct2, 4000, &s);
t1.join();
t2.join();
}
无论您在哪里更改共享数据,都必须保护您的代码。
让我用一个例子来解释你的情况:
m.lock(); // what does that mean?
// do your business
你的互斥锁 m 是厕所门。如果有人已经从另一边锁定,那么你就不能进去。所以当 m.lock()
被击中时,会发生两件事。
- 检查是否有人已经在锁着的门后
- 穿过并锁上门
现在想象一下通往同一个厕所但没有锁的另一种方式。只是一扇门,没有安全保障。
// No m.lock() here
不管另一扇门有没有锁,任何人都可以随时加入WC(不酷)。
现在想象第三种情况。
m2.lock();
// Do other stuff
现在你有了另一扇门,但有另一把锁。所以两个人可以同时进入门。在代码类比中,如果muted reference不一样,那么代码就不安全了。
我想测试一个场景,我检查 weak_ptr 有效性和 return shared_ptr。在检查和 returning 之间,如果其他线程删除了 shared_ptr,我们将面临异常。我尝试使用 windows sleep 或 cout 模拟相同的场景,但它似乎不起作用。代码如下:
#include <iostream>
#include <thread>
#include <windows.h>
#include <mutex>
using namespace std;
mutex m;
struct Block
{
int * p_ = nullptr;
Block() { p_ = new int[10000]; refCount_++; }
~Block() { delete[] p_; _p = nullptr; }
int refCount_;
};
struct Weak_ptr
{
Block * p_ = nullptr;
Weak_ptr() { p_ = new Block(); }
void Addref() { p_->refCount_++; }
void release() { delete[] p_; p_ = nullptr; cout << "\nptr deleted\n"; }
};
void funct1(int x, Weak_ptr *ptr)
{
cout << "\nin thread 1 \n";
cout << "\nSleep thread 1\n";
//Sleep(x)
for (int i = 0; i < x; i++)
cout << ".";
cout << "\nAwake thread 1\n";
ptr->release();
}
void funct2(int x, Weak_ptr *ptr)
{
m.lock();
cout << "\nin thread 2 \n";
if (ptr->p_)
{
cout << "\nptr checked \n";
//Sleep(x)
for (int i = 0; i < x; i++)
cout << "|";
cout << "\nusing ptr in t2\n";
ptr->Addref();
}
else
{
cout << "\ncheck succeeded \n";
}
m.unlock();
}
int main()
{
Weak_ptr s;
thread t1(&funct1, 2000, &s);
thread t2(&funct2, 4000, &s);
t1.join();
t2.join();
}
无论您在哪里更改共享数据,都必须保护您的代码。
让我用一个例子来解释你的情况:
m.lock(); // what does that mean?
// do your business
你的互斥锁 m 是厕所门。如果有人已经从另一边锁定,那么你就不能进去。所以当 m.lock()
被击中时,会发生两件事。
- 检查是否有人已经在锁着的门后
- 穿过并锁上门
现在想象一下通往同一个厕所但没有锁的另一种方式。只是一扇门,没有安全保障。
// No m.lock() here
不管另一扇门有没有锁,任何人都可以随时加入WC(不酷)。
现在想象第三种情况。
m2.lock();
// Do other stuff
现在你有了另一扇门,但有另一把锁。所以两个人可以同时进入门。在代码类比中,如果muted reference不一样,那么代码就不安全了。