gpt4 book ai didi

c++ - 为什么这段C++代码没有同步

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:40:12 24 4
gpt4 key购买 nike

我正在学习编写多线程应用程序。因此,尽管使用了互斥锁,但只要我希望我的线程访问简单的共享资源,我就会遇到麻烦。

例如,考虑这段代码:

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;
}

当我运行该程序时,它的行为异常。有时,值 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;

}

但是我有时会得到以下输出:

*** 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]

更新&解决方案

对于我遇到的问题(即:程序的不可预测执行以及间歇性转储损坏投诉),所有问题都通过将 -lpthread 作为我的 eclipse 构建(在项目设置下)的一部分来解决。

我正在使用 C++11。奇怪的是,至少对我来说,该程序会编译而不会发出我尚未链接到 pthread 的投诉。

所以对于任何使用 C++11、std::thread 和 linux 的人,请确保链接到 pthread,否则你的程序运行时间将非常不可预测,而且会出现错误。

最佳答案

如果您打算使用线程,我建议您至少以不同的方式完成这项工作。

现在,一个线程获得互斥锁,执行所有它要做的事情(包括休眠 3000 微秒),然后退出。然后另一个线程基本上做同样的事情。在这种情况下,线程基本上没有完成任何积极的事情,而有相当多的消极事情(同步代码等)。

您当前的代码在异常方面几乎是不安全的——如果在您的线程函数之一中抛出异常,即使该线程无法再执行,互斥量也不会被解锁。

最后,现在,您公开了一个互斥锁,并将其留给所有访问关联资源的代码以正确使用互斥锁。我更愿意集中互斥锁定,这样它的异常安全,并且大多数代码可以完全忽略它。

// use std::lock_guard, if available.
class lock {
mutex &m
public:
lock(mutex &m) : m(m) { m.lock(); }
~lock() { m.unlock(); }
};

class synched_vec {
mutex m;
std::vector<string> data;
public:
void push_back(std::string const &s) {
lock l(m);
data.push_back(s);
}
} ob;

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

这也意味着如果(例如)你决定在未来使用无锁(或最小锁定)结构,你应该只需要修改 synched_vec,而不是所有其他的使用它的代码。同样,通过将所有互斥锁处理放在一个地方,可以更容易地编写正确的代码,而且如果您确实发现了错误,也更容易确保已修复它(而不是查看所有客户端代码)。

关于c++ - 为什么这段C++代码没有同步,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16802706/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com