admin管理员组

文章数量:1311622

I'm using unique_locks and normal lock to lead the threads. I try to interlink the threads, so they don't loose too many cycles and work together and not separately. I don't know, if my code can create a dead-lock:

#include <iostream>

#include <thread>
#include <mutex>
#include <chrono>
#include <condition_variable>

std::mutex mutex1;
std::mutex mutex2;

std::condition_variable cv;
int buffer;

bool notify;

void task(std::string threadName, int loopmax) {

    for(int i = 0; i < loopmax; i++) {

        mutex1.lock();//normal lock for both threads
        buffer++;
        std::cout << threadName << buffer << "\n";
        mutex1.unlock();//normal unlock for both threads
    }
}

int main() {

    std::thread thr1([&] {

        std::unique_lock<std::mutex> lock(mutex2);//unique_lock in working_thread

        for(int j = 0; j < 3; j++) {

            task("working_thread: ", 50);
        }

        notify = true;
        std::cout << "worker complete\n";

        cv.notify_one();
    });
    
    task("Main_thread: ", 50);//can I do the task-functions here?
    task("Main_thread: ", 50);

    std::unique_lock<std::mutex> lock(mutex2);//unique_lock in main_thread

    //if I use the task-function here, the threads don't interlink anymore

    if(!notify) {

        cv.wait(lock);
    }

    printf("Hallo\n");

    thr1.join();

    return 0;
}

I always got a good interlinked output of both threads this way. Could it create a dead-lock, if the working_thread locks its unique_lock and and the main_thread locks mutex1 in the task-function ? Could it also create a dead-lock somewhere else?

I'm using unique_locks and normal lock to lead the threads. I try to interlink the threads, so they don't loose too many cycles and work together and not separately. I don't know, if my code can create a dead-lock:

#include <iostream>

#include <thread>
#include <mutex>
#include <chrono>
#include <condition_variable>

std::mutex mutex1;
std::mutex mutex2;

std::condition_variable cv;
int buffer;

bool notify;

void task(std::string threadName, int loopmax) {

    for(int i = 0; i < loopmax; i++) {

        mutex1.lock();//normal lock for both threads
        buffer++;
        std::cout << threadName << buffer << "\n";
        mutex1.unlock();//normal unlock for both threads
    }
}

int main() {

    std::thread thr1([&] {

        std::unique_lock<std::mutex> lock(mutex2);//unique_lock in working_thread

        for(int j = 0; j < 3; j++) {

            task("working_thread: ", 50);
        }

        notify = true;
        std::cout << "worker complete\n";

        cv.notify_one();
    });
    
    task("Main_thread: ", 50);//can I do the task-functions here?
    task("Main_thread: ", 50);

    std::unique_lock<std::mutex> lock(mutex2);//unique_lock in main_thread

    //if I use the task-function here, the threads don't interlink anymore

    if(!notify) {

        cv.wait(lock);
    }

    printf("Hallo\n");

    thr1.join();

    return 0;
}

I always got a good interlinked output of both threads this way. Could it create a dead-lock, if the working_thread locks its unique_lock and and the main_thread locks mutex1 in the task-function ? Could it also create a dead-lock somewhere else?

Share Improve this question asked Feb 3 at 13:34 Lukas_macht_dasLukas_macht_das 11 bronze badge 10
  • 1 Did you run this code through thread sanitizer? – Eljay Commented Feb 3 at 13:40
  • 3 How could it deadlock? There is no path where a thread attempts to lock mutex2 while already holding mutex1. – Mestkon Commented Feb 3 at 13:51
  • 1 @JérômeRichard globals are intialized – 463035818_is_not_an_ai Commented Feb 3 at 14:02
  • 3 if(! notify) cv.wait(lock); is wrong. cv.wait can return spuriously. It has to be a loop, while(! notify) cv.wait(lock); – Homer512 Commented Feb 3 at 14:05
  • 2 You're trying to compare "unique_lock" (the name of a class) to "lock" (an action performed on a mutex.) IMO, that's over-complicating things. The only thing that matters is the state of the mutex. unique_lock is just a different way of controlling the state of the mutex. – Ohm's Lawman Commented Feb 3 at 14:23
 |  Show 5 more comments

1 Answer 1

Reset to default 2

As from Here:

A deadlock requires four conditions: mutual exclusion, hold and wait, no preemption, and circular wait.

Thanks to @463035818_is_not_an_ai, Wikipedia has a better and more detailed description to the four conditions.

It does not matter matter if you use a unique lock or normal lock, any waiting operation which fulfills the four conditions can cause a deadlock.

The current code does not fulfill the deadlock conditions
As @Mestkon has pointed out in the comments, in your code every thread currently uses only one mutex, thus it is impossible to fulfil the "hold and wait" condition. Thus no deadlock can happen.

Define a locking sequence
A usually simple practical approach is to define a locking sequence and use it everywhere.
For example if you ever need mutex1 and mutex2 at the same time, make sure to always lock mutex1 first, then mutex2 second (or always the other way around).
By that you can easily prevent the "circular wait" (mutex1 waiting for mutex2 and mutex2 waiting for mutex1) condition, thus no deadlock can happen.

本文标签: cCan a uniquelock and a normal lock cause together a deadlockStack Overflow