如果互斥锁只能被锁定一次,我怎么可能多次锁定互斥锁?

问题描述 投票:0回答:1

我试图理解 C++ 信号量和互斥体,我发现我多次锁定 1 个互斥体,或者至少我的调试消息显示情况是这样。 尽管我们在信号量中只有 1 个互斥体,但我正在为超过 1 个线程获取它。 我知道信号量应该允许多线程访问(受计数器限制),但内部信号量由互斥体组成,互斥体的值可以为 0 或 1,无论是否采用。 在我看来,2 个线程不可能依次锁定互斥锁 1,但我可以在日志文件中看到这一点

/**
 * Connecting cell phones to a charger
 */
#include <thread>
#include <chrono>
#include <mutex>
#include <condition_variable>
#include <cstdio>
#include <bits/stdc++.h>

unsigned int data_race = 0;

class Semaphore {
public:
    Semaphore(unsigned long init_count) {
        count_ = init_count;
    }

    void acquire(int id) { // decrement the internal counter
        printf("%d wants to aquire.\n", id);
        std::unique_lock<std::mutex> lck(m_);
        printf("%d aquired mutex in aquire\n", id);
        while (!count_) {
            printf("%d is waiting for lock\n", id);
            cv_.wait(lck);
        }
        printf("%d is about to decrease count\n", id);
        count_--;
    }

    void release(int id) { // increment the internal counter
        printf("%d is about to relase \n", id);
        std::unique_lock<std::mutex> lck(m_);
        printf("%d acuired mutex in release\n", id);
        count_++;
        lck.unlock();
       cv_.notify_one();
    }

private:
    std::mutex m_;
    std::condition_variable cv_;
    unsigned long count_;
};

Semaphore charger(2);

void cell_phone(int id) {
    charger.acquire(id);
    printf("Phone %d is charging...\n", id);
    srand(id); // charge for "random" amount between 1-3 seconds
    std::this_thread::sleep_for(std::chrono::milliseconds(rand() % 2000 + 1000));
    printf("Phone %d is DONE charging!\n", id);
    charger.release(id);
}

int main() {
    std::thread phones[6];
    for (int i=0; i<6; i++) {
        phones[i] = std::thread(cell_phone, i);
    }
    for (auto& p : phones) {
        p.join();
    }
}

它是用c++17编译的,我认为在这个实现中一次只会获取1个互斥量。

结果:

PS C:\HHardDrive\embedded C\output> & .\'Semaphore_CriticalSection2.exe'
0 wants to aquire.
0 aquired mutex in aquire    //->Mutex locked first time
0 is about to decrease count
Phone 0 is charging...      
4 wants to aquire.
4 aquired mutex in aquire    //->Mutex locked second time
4 is about to decrease count
Phone 4 is charging...      
3 wants to aquire.
3 aquired mutex in aquire   
3 is waiting for lock       
2 wants to aquire.
2 aquired mutex in aquire   
2 is waiting for lock       
5 wants to aquire.
5 aquired mutex in aquire
1 wants to aquire.
5 is waiting for lock
1 aquired mutex in aquire
1 is waiting for lock
Phone 0 is DONE charging!
0 is about to relase 
0 acuired mutex in release
Phone 4 is DONE charging!
3 is about to decrease count
4 is about to relase
4 acuired mutex in release
Phone 3 is charging...
2 is about to decrease count
Phone 2 is charging...
Phone 2 is DONE charging!
2 is about to relase 
Phone 3 is DONE charging!
2 acuired mutex in release
3 is about to relase
5 is about to decrease count
Phone 5 is charging...
3 acuired mutex in release
1 is about to decrease count
Phone 1 is charging...
Phone 1 is DONE charging!
Phone 5 is DONE charging!
1 is about to relase
5 is about to relase 
1 acuired mutex in release
5 acuired mutex in release
c++ mutex semaphore
1个回答
0
投票

线程 0 在

acquire()
的析构函数中解锁了
std::unique_lock<std::mutex> lck
中的互斥锁,该析构函数在退出定义它的块时执行。 这发生在
acquire
返回之前,并且在打印消息“0 即将减少计数”之后不久。 所以线程 0 确实在线程 4 锁定锁之前解锁了锁。

这个 RAII 模式就是

unique_lock
的全部要点;它有效地从定义点开始一直持有锁,直到封闭块的末尾,然后将其解锁。

© www.soinside.com 2019 - 2024. All rights reserved.