Mutex&线程:解释

时间:2016-11-01 22:27:42

标签: c++ multithreading mutex

我一直在阅读以下教程:C++ Multithreading Tutorial。 我已经在教程中编译了代码,该代码创建了十个唯一的线程并打印了一个带有线程编号的字符串。

以下是那些不想打开链接的人的代码:

#include <iostream>
#include <thread>

static const int num_threads = 10;

//This function will be called from a thread

void call_from_thread(int tid) {
    std::cout << "Launched by thread " << tid << std::endl;
}

int main() {
    std::thread t[num_threads];

    //Launch a group of threads
    for (int i = 0; i < num_threads; ++i) {
        t[i] = std::thread(call_from_thread, i);
    }

    std::cout << "Launched from the main\n";

    //Join the threads with the main thread
    for (int i = 0; i < num_threads; ++i) {
        t[i].join();
    }

    return 0;
}

当我运行代码时,它会编译并且输出是随机的。 它将启动每个线程,但它不会按顺序启动它们。

我正在阅读std :: mutex上的C ++参考资料,听起来就像我需要的那样。

所以,我想知道是否有人可以快速了解如何在这样的代码中实现std:mutex,以确保线程不使用相同的共享资源并确保它们按顺序发布。

1 个答案:

答案 0 :(得分:1)

线程是按正确的顺序创建的,但其执行的调度顺序并不保证是相同的。

互斥是解决方案吗?

您可以尝试添加互斥锁。这只能确保两个线程同时不在关键部分:

std::mutex mtx; 

void call_from_thread(int tid) {
    std::lock_guard<std::mutex> lock(mtx);  // holds the lock until scope is left
    std::cout << "Launched by thread " << tid << std::endl;
}

请注意,我没有直接锁定互斥锁,而且我更喜欢lock_guard:这会使用异常安全的RAII来锁定互斥锁。

Online demo 1

原子解决方案

在没有互斥锁的情况下进行多线程处理的另一种方法是使用原子变量。保证一次只能访问一个线程而不进行数据竞争。

std::atomic<int> cnt{0}; 

void call_from_thread(int tid) {
    while (cnt!=tid) 
        std::this_thread::yield();  
    std::cout << "Launched by thread " << tid << std::endl;
    cnt++; 
}

当然上面的代码是无用的:它只是确保线程按顺序执行。每个线程看起来全局原子计数器对应于它的数字。如果是,则执行并递增全局计数器。如果没有,它只是给另一个线程执行的机会。

Online demo 2

当然这里的构造是浪费时间。通常,您使用条件变量来执行此类操作。它仅用于说明。

<强>结论

多线程非常复杂。如果你想深入研究它,我强烈推荐Anthony William的书&#34; C ++ Concurrency in action&#34;这是一个很好的一步一步的介绍,不仅是对C ++多线程库,还有更普遍的挑战多线程算法。