Почему мьютекс не работает с двумя потоками, совместно использующими ресурс? - PullRequest
0 голосов
/ 13 января 2020

Я хочу протестировать сценарий, в котором я проверяю правильность 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 Ответ

2 голосов
/ 13 января 2020

Вы должны защищать свой код везде, где вы меняете общие данные.

Позвольте мне объяснить вашу ситуацию на примере:

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

Ваш мьютекс m - это дверь W C. Если кто-то уже блокируется с другой стороны, то вы не можете go войти. Поэтому, когда ударил m.lock(), происходят две вещи.

  1. Проверьте, находится ли кто-нибудь уже за запертой дверью
  2. Go и заприте дверь

Теперь представьте себе другой путь, ведущий к тому же Ш C но без замка. Просто дверь без охраны.

// No m.lock() here

Независимо от того, заперта ли другая дверь, не имеет значения, любой может присоединиться к W C в любое время (не круто).

Теперь представьте себе третью ситуацию ,

m2.lock();
// Do other stuff

Теперь у вас есть другая дверь, но с другим замком. Таким образом, два человека могут получить доступ к двери одновременно. В аналогии с кодом, если приглушенная ссылка не совпадает, код не является безопасным.

...