为什么这段C++代码不同步

uka*_*aku 5 c++ multithreading synchronization mutex

我正在学习编写多线程应用程序.因此,即使使用互斥锁,我也希望我的线程能够访问简单的共享资源.

例如,考虑以下代码:

using namespace std;
mutex mu;
std::vector<string> ob;

void addSomeAValues(){
    mu.lock();    
    for(int a=0; a<10; a++){
        ob.push_back("A" + std::to_string(a));
        usleep(300);    
    }
    mu.unlock();
}

void addSomeBValues(){    
    mu.lock();    
    for(int b=0; b<10; b++){            
        ob.push_back("B" + std::to_string(b));        
        usleep(300);    
    }   
    mu.unlock();
}

int main() {    
    std::chrono::steady_clock::time_point start = std::chrono::steady_clock::now();        
    thread t0(addSomeAValues);        
    thread t1(addSomeBValues);    
    std::chrono::steady_clock::time_point end = std::chrono::steady_clock::now();

    t0.join();
    t1.join();

    //Display the results
    cout << "Code Run Complete; results: \n";    
    for(auto k : ob){
        cout << k <<endl;
    }
    //Code running complete, report the time it took
    typedef std::chrono::duration<int,std::milli> millisecs_t;
    millisecs_t duration(std::chrono::duration_cast<millisecs_t>(end-start));
    std::cout << duration.count() << " milliseconds.\n";
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

当我运行程序时,它的行为无法预测.有时,值A0-9和B0-9打印到控制台没有问题,有时会出现崩溃报告的分段错误,有时会出现A0-3和B0-5.

如果我错过了核心同步问题,请求帮助

编辑:经过大量有用的反馈,我将代码更改为

#include <iostream>
#include <string>
#include <vector>
#include <mutex>
#include <unistd.h>
#include <thread>
#include <chrono>

using namespace std;
mutex mu;
std::vector<string> ob;

void addSomeAValues(){

for(int a=0; a<10; a++){
    mu.lock();
        ob.push_back("A" + std::to_string(a));
    mu.unlock();
    usleep(300);
}
}

void addSomeBValues(){
for(int b=0; b<10; b++){
    mu.lock();
        ob.push_back("B" + std::to_string(b));
    mu.unlock();

    usleep(300);
}
}

int main() {

std::chrono::steady_clock::time_point    start = std::chrono::steady_clock::now() ;

    thread t0(addSomeAValues);
    thread t1(addSomeBValues);

std::chrono::steady_clock::time_point       end = std::chrono::steady_clock::now() ;

t0.join();
t1.join();

//Display the results
cout << "Code Run Complete; results: \n";
for(auto k : ob){
    cout << k <<endl;
}
//Code running complete, report the time it took
    typedef std::chrono::duration<int,std::milli> millisecs_t ;
    millisecs_t duration( std::chrono::duration_cast<millisecs_t>(end-start) ) ;
    std::cout << duration.count() << " milliseconds.\n" ;
return 0;

}
Run Code Online (Sandbox Code Playgroud)

但有时我得到以下输出:

*** Error in `/home/soliduscode/eclipse_workspace/CppExperiment/Debug/CppExperiment':
double free or corruption (fasttop): 0x00007f19fc000920 ***
======= Backtrace: =========
/lib/x86_64-linux-gnu/libc.so.6(+0x80a46)[0x7f1a0687da46]
/home/soliduscode/eclipse_workspace/CppExperiment/Debug/CppExperiment[0x402dd4]
/home/soliduscode/eclipse_workspace/CppExperiment/Debug/CppExperiment[0x402930]
/home/soliduscode/eclipse_workspace/CppExperiment/Debug/CppExperiment[0x402a8d]
/home/soliduscode/eclipse_workspace/CppExperiment/Debug/CppExperiment[0x402637
/home/soliduscode/eclipse_workspace/CppExperiment/Debug/CppExperiment[0x402278]
/home/soliduscode/eclipse_workspace/CppExperiment/Debug/CppExperiment[0x4019cf]
/home/soliduscode/eclipse_workspace/CppExperiment/Debug/CppExperiment[0x4041e3]
/home/soliduscode/eclipse_workspace/CppExperiment/Debug/CppExperiment[0x404133]
/home/soliduscode/eclipse_workspace/CppExperiment/Debug/CppExperiment[0x404088]
/usr/lib/x86_64-linux-gnu/libstdc++.so.6(+0xb29f0)[0x7f1a06e8d9f0]
/lib/x86_64-linux-gnu/libpthread.so.0(+0x7f8e)[0x7f1a060c6f8e]
/lib/x86_64-linux-gnu/libc.so.6(clone+0x6d)[0x7f1a068f6e1d]
Run Code Online (Sandbox Code Playgroud)

更新和解决方案

这个问题我正经历(即:以贪污投诉的间歇转储程序的不可预知的执行),都被包括-lpthread我的Eclipse构建(在项目设置)的部分解决.

我正在使用C++ 11.至少对我而言,奇怪的是,该程序将编译而不会发出我尚未与pthread相关联的投诉.

因此对于使用C++ 11,std :: thread和linux的任何人来说,请确保链接到pthread,否则你的程序运行时将非常难以预测,并且有错误.

typ*_*232 0

问题中的代码运行时没有任何分段错误(添加标头并将睡眠替换为我的系统的睡眠)。

但该代码存在两个问题,可能会导致意外结果:

  • 每个线程在其完整执行期间都会锁定互斥体。这会阻止其他线程运行。两个线程不是并行运行的!在你的情况下,你应该只在访问向量时锁定。

  • 您的结束时间点是在创建线程之后而不是在线程执行完毕之后获取的。当两个线程都被编辑时,它们就完成了join

使用标头、chrono-sleep 工作可编译代码并修复了两个错误:

#include <mutex>
#include <string>
#include <vector>
#include <thread>
#include <iostream>


std::mutex mu;
std::vector<std::string> ob;

void addSomeAValues(){
    for(int a=0; a<10; a++){
        mu.lock();
        ob.push_back("A" + std::to_string(a));
        mu.unlock();
        std::this_thread::sleep_for(std::chrono::milliseconds(300));
    }
}

void addSomeBValues(){
    for(int b=0; b<10; b++){            
        mu.lock();
        ob.push_back("B" + std::to_string(b));        
        mu.unlock();
        std::this_thread::sleep_for(std::chrono::milliseconds(300));
    }
}

int main() {    
    std::chrono::steady_clock::time_point start = std::chrono::steady_clock::now();        
    std::thread t0(addSomeAValues);        
    std::thread t1(addSomeBValues);    

    t0.join();
    t1.join();
    std::chrono::steady_clock::time_point end = std::chrono::steady_clock::now();

    //Display the results
    std::cout << "Code Run Complete; results: \n";    
    for(auto k : ob){
        std::cout << k << std::endl;
    }
    //Code running complete, report the time it took
    typedef std::chrono::duration<int,std::milli> millisecs_t;
    millisecs_t duration(std::chrono::duration_cast<millisecs_t>(end-start));
    std::cout << duration.count() << " milliseconds.\n";

    return 0;
}
Run Code Online (Sandbox Code Playgroud)