Как применять мьютексы при передаче по значению? - PullRequest
2 голосов
/ 16 апреля 2019

Мне было интересно, как работает переменный сдвиг, когда я передаю вещи по значению.Могу ли я заблокировать мьютекс перед вызовом функции, а затем разблокировать внутри функции после входа?Является ли передача по значению предпочтительной при работе с потоками?

Mutex Que_mutex;
queue <char> Que;  //access to this must be done with Que_mutex locked
void queSizeCheck(queue<char> quet);

int main() {
//open new threads, which also manipulate Que
//some other code here, where Que.push, Que.pop and Que.front happens at some points
    Que_mutex.lock();
    queSizeCheck(Que);
}

void queSizeCheck(queue<char> quet) {
    Que_mutex.unlock();
    if (quet.size() < 3) {
        //do something
    }
}

Я работаю над mbed в C ++ 98.

Ответы [ 2 ]

3 голосов
/ 16 апреля 2019

Это одна из причин, почему передача по значению в C ++ 98 не работает.

Поскольку вы хотите удерживать блокировку в течение минимально возможного времени, в C ++ 11 и C ++ 14 я сначала скопирую очередь, затем разблокирую мьютекс, затем переместим копию в функция (при условии, что queue является подвижным).

int main() {
    std::unique_lock<Mutex> lock(Que_mutex);
    auto copy = Que;
    lock.unlock();
    queSizeCheck(std::move(copy));
}

Поскольку вопрос помечен C ++ 98, мы не можем использовать семантику перемещения. В этом случае я бы инкапсулировал копирование в отдельную функцию и полагался на то, что компилятор достаточно умен, чтобы применять elision copy:

queue<char> queCopy() {
    // lock_guard is C++11 but you can easily write your own C++98 implementation
    std::lock_guard<Mutex> lock(Que_mutex);

    // hope the compiler is smart enough to directly initialize the parameter
    // of queSizeCheck without incurring additional copies
    return Que;
}

int main() {
    queSizeCheck(queCopy());
}

Это зависит от того, что компилятор удаляет копию возвращаемого значения queCopy и аргумента queSizeCheck. И заканчивается тем, что код на самом деле более хорошо организован, чем код C ++ 11. Начиная с C ++ 17, это снова становится лучшим решением благодаря обязательному исключению копирования.

Все это предполагает разумную реализацию queue, которая не была показана в вопросе.

0 голосов
/ 16 апреля 2019

Конечно. Вы даже не проходите mutex здесь. Вы используете тот же mutex.
Будет разблокировано.

Даже если вы передадите mutex в функцию. Он все еще будет разблокирован.

Тем не менее. Не разумно блокировать mutex в одной функции и разблокировать ее в другой. Вы должны использовать такой подход.

mutex.lock()
//... some operations on the data structure
mutex.unlock()

Вы можете посмотреть на RAII способ сделать это с помощью lock_guard .

...