首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何修复C++线程死锁示例

如何修复C++线程死锁示例
EN

Stack Overflow用户
提问于 2014-09-04 08:08:42
回答 2查看 5.9K关注 0票数 4

我设计了一个C++11线程死锁。这是使用两个具有多个线程池的独立函数来实现的。如何修正此示例以避免死锁?我认为这个解决方案与锁程序的顺序一致有关。

代码语言:javascript
复制
#include <thread>
#include <mutex>
#include <iostream>

std::mutex kettle;
std::mutex tap;

#define THREAD_POOL 8

void kettle_tap(){

    std::cout << "Locking kettle in " << std::this_thread::get_id() << std::endl;
    // Lock the mutex kettle by creating and using lock_guard kettle_lock.
    std::lock_guard<std::mutex> kettle_lock(kettle);
    std::cout << "Locked kettle in " << std::this_thread::get_id() << std::endl;

    std::cout << "Locking tap in " << std::this_thread::get_id() << std::endl;
    // Lock the mutex tap by creating and using lock_guard tap_lock.
    std::lock_guard<std::mutex> tap_lock(tap);
    std::cout << "Locked tap in " << std::this_thread::get_id() << std::endl;

    std::cout << "Filling kettle in " << std::this_thread::get_id() << std::endl;
}

void tap_kettle(){

    std::cout << "Locking tap in " << std::this_thread::get_id() << std::endl;
    // Lock the mutex tap by creating and using lock_guard tap_lock.
    std::lock_guard<std::mutex> tap_lock(tap);
    std::cout << "Locked tap in " << std::this_thread::get_id() << std::endl;

    std::cout << "Locking kettle in " << std::this_thread::get_id() << std::endl;
    // Lock the mutex kettle by creating and using lock_guard kettle_lock.
    std::lock_guard<std::mutex> kettle_lock(kettle);
    std::cout << "Locked kettle in " << std::this_thread::get_id() << std::endl;

    std::cout << "Filling kettle in " << std::this_thread::get_id() << std::endl;

}

int main(){

    std::thread pool[THREAD_POOL];

    for (int t = 0; t < THREAD_POOL; t += 2){
        pool[t]   = std::thread(kettle_tap);
        pool[t+1] = std::thread(tap_kettle);
    }

    for (int t = 0; t < THREAD_POOL; ++t){
        pool[t].join();
    }

    std::cout << "Threads are all joined" << std::endl;

    return 0;

}
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-09-04 08:20:16

std::lock(Mutexes...)

在您的示例中,kettle_tap()tap_kettle()都应该以以下内容开头:

代码语言:javascript
复制
std::lock(tap, kettle);

但是互斥参数的顺序并不重要,因此可以在两个函数之间不同

锁多互斥 锁定作为参数传递的所有对象,必要时阻塞调用线程。 该函数使用对其成员的未指定的调用序列锁定对象,并锁定、try_lock和解锁,以确保所有参数在返回时都被锁定(而不产生任何死锁)。 如果函数无法锁定所有对象(例如,因为其内部调用之一抛出异常),则该函数首先在失败之前解锁它成功锁定的所有对象(如果有的话)。

稍后,如果您想将锁的所有权转移到std::lock_guard

代码语言:javascript
复制
std::lock(tap, kettle);
std::lock_guard<std::mutex> kettle_lock(kettle, std::adopt_lock);
std::lock_guard<std::mutex> tap_lock(tap, std::adopt_lock);
票数 6
EN

Stack Overflow用户

发布于 2014-09-04 08:20:08

你是正确的。通过避免循环等待,死锁可以是防制。在您的示例中,为了避免死锁,请在kettle_lock方法中将tap_lock移动到tap_lock之上。这样你就可以得到一个偏序。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/25660347

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档