【问题标题】:Mutex locked confusion互斥锁混乱
【发布时间】:2019-12-19 07:13:03
【问题描述】:

您好,我对互斥锁锁定感到困惑。我对有经验的人有一个关于多线程的问题。例如,在我的代码中,我有一个包含互斥锁和条件变量的类,我将它们用于套接字通信。我使用mutex.lock()for lock 函数的变量,但我不明白我锁定了什么。我是否锁定了函数的变量或其他东西。 我使用unique_lock 因为我想使用condition_variable 并锁定函数的变量,但我不知道它是否有效。我想创建相互等待的发送者和接收者。

我的接收数据功能

void connect_tcp::Recv_data(SOCKET s,mms_response &response,Signals *signals,bool &ok,ıvır_zıvır &ıvır) {
    LinkedList** list = new LinkedList * [1000];
    uint8_t* buffer = new uint8_t [10000];
    //ok = false;
    unique_lock <mutex> lck(ıvır.mutex);
    if (ıvır.for_data == true) {
        dataready = true;
    }
    ıvır.cv.wait(lck, [] {return dataready; });
    this_thread::sleep_for(1s);
    recv(s, (char*)buffer, 10000, 0);
    dataready = false;
    decode_bytes(response,buffer, list,signals);
    ok = true;
    ıvır.ıvır_control--;

}

我的发送数据功能

int connect_tcp::send_data(SOCKET s, mms_response &response,LinkedList** list,int &j,bool &ok, ıvır_zıvır& ıvır) {
    /*this_thread::sleep_for(0.3s);*/
    int i = 0;
    int k = 0;
    ıvır.mutex.lock();
    uint8_t* buffer = new uint8_t[10000];
    while (i<j)
    {
        for (auto it = list[i]->data.begin(); it != list[i]->data.end(); it++)
        {
            buffer[k]=*it;
            k++;

        }
        i++;

    }

    int jk = 0;

        jk= send(s, (const char*)buffer, list[0]->size, 0);
        cout << jk << " Bytes sent" << endl;

        dataready = true;
        this_thread::sleep_for(1s);
        ıvır.mutex.unlock();
        ıvır.cv.notify_one();

    if (jk == -1) {
        exit(-1);
    }
    i = 0;
    while (i<j) {
        delete list[i]; 
        i++;
    }
    j = 1;
    return jk;
}

我阅读了很多书籍和条目,但没有人解释 mutex.lock() 什么是锁定。我只看到一个解释是“如果 2 个线程想要使用相同的源 mutex.lock 被阻止,例如 stdinstdout”。

【问题讨论】:

  • 它锁定互斥体,互斥体与任何其他变量没有关系

标签: c++ multithreading locking std mutex


【解决方案1】:

互斥锁是一次只能有一个线程拥有的东西。如果没有线程接触特定变量,除非它具有特定的互斥锁,那么我们说互斥锁锁定了那个东西。

互斥锁通常用于防止多个线程同时接触某物。程序员有责任将特定的互斥锁与特定的共享资源相关联,方法是确保共享资源不会被持有适用互斥锁的线程查看或触及。

一般来说,除非您别无选择,否则您不想在持有互斥锁时做任何“繁重”的事情。尤其是打电话sleep_for 是特别愚蠢和糟糕的。 recv 同上。

【讨论】:

  • 所以如果我们有 2 个线程使用 Recv_data 函数并且当第一个线程在 recv_data 函数内部时,如果其他线程尝试通过 recv_data 函数,其他线程不能通过或等待?
  • @SerhanErkovan 这取决于这些函数在做什么。例如,如果两个线程都尝试在同一个套接字上接收,那么您将遇到一个大问题。如果他们处理不同的套接字,那完全没有问题。但通常你不需要互斥锁来阻止两个线程尝试做同样的事情,你需要互斥锁来阻止两个线程对同一个对象做不同的事情。
【解决方案2】:

我是否锁定了函数的变量或其他东西。

绝对清楚一点:如果线程 A 保持某个互斥锁 M 被锁定,那么 不会 阻止其他线程做 任何事情,除了锁定相同的互斥锁 M同一时间。

如果有人说“互斥锁 M 保护变量 x、y 和 z”,这只是表示程序经过精心编写的简写方式,因此每个线程在访问任何这些变量之前总是锁定互斥锁 M。

此处的其他答案对此进行了更详细的说明...

【讨论】:

    【解决方案3】:

    来自cppreference

    The mutex class is a synchronization primitive that can be used to protect shared data from being simultaneously accessed by multiple threads.

    顾名思义,互斥锁是一种互斥状态持有者,可以以原子方式在线程之间公开单个状态(锁定状态)。锁定是通过unique_lock、shared_lock等不同的机制实现的。

    另外说明:您的代码有几个问题:

    1. Recv_data 函数(分配)中的前两行将在函数返回后泄漏。看看RAII,了解如何在现代 c++ 中初始化和分配
    2. 由于您使用线程锁和互斥锁,因此不需要条件变量。 mutex会保证线程的互斥,不需要通知。但是,这在很大程度上取决于您生成线程的方式。
    3. 您正在混合使用两个概念,即套接字通信和线程。这似乎有点可疑。也就是说,不清楚您的函数是从哪个上下文调用的(不同的进程?在这种情况下,讨论线程是没有意义的)。

    我建议您简化用于发送和接收单个变量(而不是数组)的代码,以先了解基础知识,然后再转向更复杂的用例。

    【讨论】:

      猜你喜欢
      • 2018-05-23
      • 1970-01-01
      • 2010-09-16
      • 2010-12-17
      • 2012-06-05
      • 1970-01-01
      • 1970-01-01
      • 2015-10-26
      • 2022-07-31
      相关资源
      最近更新 更多