【问题标题】:Why mutex is not working with 2 threads sharing resource?为什么互斥锁不能与 2 个线程共享资源一起使用?
【发布时间】:2020-04-29 20:27:08
【问题描述】:

我想测试一个场景,我检查weak_ptr 的有效性并返回shared_ptr。在检查和返回是否有其他线程删除 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();
}

【问题讨论】:

  • 互斥锁不是单方面的交易。访问资源的所有线程都需要使用相同的互斥锁。这是一个合作的事情。
  • 错误 #1:当构造函数完成时,Block 上的 refCount_ 成员具有未定义的值。您需要将refCount 显式初始化为1,而不是增加未定义的值。
  • 你能发布你的程序的输出吗?它会触发异常吗?
  • 错误 #2:Weak_ptr::release 只是盲目地删除底层对象,而不管 refCount_ 成员的值如何。我希望它会减少 refCount,然后如果它变为零则删除。
  • 有两个智能指针模板std::shared_ptrstd::weak_ptr 似乎完全符合您的目标。你为什么不用那些?即使没有,您也可以查看他们的实现,了解他们如何解决您的问题。

标签: c++ multithreading mutex stdthread


【解决方案1】:

无论您在何处更改共享数据,都必须保护您的代码。

让我用一个例子来解释一下你的情况:

m.lock(); // what does that mean?
// do your business

您的互斥锁 m 是 WC 门。如果有人已经从另一边锁定,那么你不能进去。所以当m.lock() 被击中时会发生两件事。

  1. 检查是否有人已经在锁着的门后
  2. 进去锁门

现在想象另一种通向同一个 WC 但没有锁的方式。只是一扇没有保安的门。

// No m.lock() here

另一扇门是否锁上都没关系,任何人都可以随时加入WC(不酷)。

现在想象第三种情况。

m2.lock();
// Do other stuff

现在你有了另一扇门,但有另一把锁。所以两个人可以同时进门。在代码类比中,如果静音引用不同,则代码不安全。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-04
    • 2021-07-28
    • 1970-01-01
    • 2021-10-10
    • 2011-07-22
    相关资源
    最近更新 更多