Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何确保两个线程中的两个类编写相同的变量是线程安全的?_C++_Multithreading_Mutex - Fatal编程技术网

C++ 如何确保两个线程中的两个类编写相同的变量是线程安全的?

C++ 如何确保两个线程中的两个类编写相同的变量是线程安全的?,c++,multithreading,mutex,C++,Multithreading,Mutex,我有两个类同时在两个线程中运行,比如classA和classB,A正在从一些API收集数据,并不断将更新的数据推送到一个无序的映射中,如B->m。同时,B正在使用数据创建自定义类Bar,代码如下: 类A: if(m.size() > 0){ //mtx.lock(); lock = B->lock; if(lock == false){ lock = true; B->m = m; lock = false; } m.clear(); //mtx.

我有两个类同时在两个线程中运行,比如class
A
和class
B
A
正在从一些API收集数据,并不断将更新的数据推送到一个
无序的映射中,如
B->m
。同时,
B
正在使用数据创建自定义类
Bar
,代码如下:

A

if(m.size() > 0){
//mtx.lock();
lock = B->lock;
if(lock == false){
  lock = true;
  B->m = m;     
  lock = false;
}    
m.clear();
//mtx.unlock();
}
 while(true){
    if(m.size() > 0){
        //mtx.lock();
        if(lock == false){
            lock = true;
            for (auto it : m) {
              std::string symbol = it.first;
              std::vector<double> v = it.second;
              Bar b;
              b.open = v[0];
              b.high = v[1];                
              bars.push_back(b);
            }
            m.clear();

            lock = false;
        }
        //mtx.unlock();
    }}
B

if(m.size() > 0){
//mtx.lock();
lock = B->lock;
if(lock == false){
  lock = true;
  B->m = m;     
  lock = false;
}    
m.clear();
//mtx.unlock();
}
 while(true){
    if(m.size() > 0){
        //mtx.lock();
        if(lock == false){
            lock = true;
            for (auto it : m) {
              std::string symbol = it.first;
              std::vector<double> v = it.second;
              Bar b;
              b.open = v[0];
              b.high = v[1];                
              bars.push_back(b);
            }
            m.clear();

            lock = false;
        }
        //mtx.unlock();
    }}
while(true){
如果(m.size()>0){
//mtx.lock();
if(lock==false){
lock=true;
用于(自动it:m){
std::string symbol=it.first;
std::vector v=it.second;
b栏;
b、 开路=v[0];
b、 高=v[1];
杆。推回(b);
}
m、 清除();
锁=假;
}
//mtx.unlock();
}}

从这里可以看出,我曾尝试使用一个名为
lock
的布尔值手动实现互斥锁,当我编译时,它有时会结束,有时会出现seg错误,我认为这是因为边缘情况:当我在class
B
中将
lock
设置为
true
时,class
a
刚刚跳过了
if(lock==false)
B
正在读取由
A
更改的数据。我的问题是,如何避免这种情况发生

手动互斥实现将无法工作(至少不容易)。例如,从编译器的角度来看

lock = strategy->lock;
if(lock == false){
  lock = true;
  B->m = m;     
  lock = false;
}
可以重新调整到这个位置

lock = strategy->lock;
if(lock == false){
  B->m = m;
}
因为单线程结果(如果您不告诉它,这是编译器的默认观点)是完全相同的

还有其他可能失败的原因,例如部分对象填充。通常是复杂的东西

因此,您必须使用正在使用的库提供给您的某些同步对象。对于C++11及更高版本,您只需使用:

#包括
std::mutex my_mutex;
...
//一些代码
{
//锁资源
std::锁定保护lg(我的互斥);
B->m=m;
}
//自动释放锁并继续执行

手动互斥实现将无法工作(至少不容易实现)。例如,从编译器的角度来看

lock = strategy->lock;
if(lock == false){
  lock = true;
  B->m = m;     
  lock = false;
}
可以重新调整到这个位置

lock = strategy->lock;
if(lock == false){
  B->m = m;
}
因为单线程结果(如果您不告诉它,这是编译器的默认观点)是完全相同的

还有其他可能失败的原因,例如部分对象填充。通常是复杂的东西

因此,您必须使用正在使用的库提供给您的某些同步对象。对于C++11及更高版本,您只需使用:

#包括
std::mutex my_mutex;
...
//一些代码
{
//锁资源
std::锁定保护lg(我的互斥);
B->m=m;
}
//自动释放锁并继续执行

您需要std::mutex和std::condition\u变量

std::mutex
用于保护代码不受未定义行为的影响,以及
std::condition_variable
用于通知工作线程需要完成一些工作

如果您确实想实现互斥,那么请确保您使用的是原子类型,例如
std::atomic_flag
std::atomic


为自己实现一个“线程安全”容器是解决您的问题的一个简单选择,它将类似于(尚未测试,只是为了查看):

#包括
#包括
#包括
模板
类容器{
公众:
bool Get(常量键和键、值和值){
标准:锁紧保护装置(mtx);
auto ite=mp_.find(键);
如果(ite==mp_u2;end())
返回false;
值=标准::移动(现场->秒);
mp_.擦除(ite);
返回true;
}
模板
无效插入(常量键和键、值类型和值){
标准:锁紧保护装置(mtx);
mp_u[key]=std::forward(值);
}
私人:
std::无序地图mp;
std::互斥mtx;
};

在实现并发算法时,有很多事情需要注意,我建议您首先阅读一些关于这个主题的书籍(不要担心,无论如何,您都会以艰苦的方式学习它们)。“C++并发运行”是一个良好的开端。

您需要std::mutex和std::condition\u变量

std::mutex
用于保护代码不受未定义行为的影响,以及
std::condition_variable
用于通知工作线程需要完成一些工作

如果您确实想实现互斥,那么请确保您使用的是原子类型,例如
std::atomic_flag
std::atomic


为自己实现一个“线程安全”容器是解决您的问题的一个简单选择,它将类似于(尚未测试,只是为了查看):

#包括
#包括
#包括
模板
类容器{
公众:
bool Get(常量键和键、值和值){
标准:锁紧保护装置(mtx);
auto ite=mp_.find(键);
如果(ite==mp_u2;end())
返回false;
值=标准::移动(现场->秒);
mp_.擦除(ite);
返回true;
}
模板
无效插入(常量键和键、值类型和值){
标准:锁紧保护装置(mtx);
mp_u[key]=std::forward(值);
}
私人:
std::无序地图mp;
std::互斥mtx;
};

在实现并发算法时,有很多事情需要注意,我建议您首先阅读一些关于这个主题的书籍(不要担心,无论如何,您都会以艰苦的方式学习它们)。“C++并发运行”是一个良好的开端。

手动互斥实现将无法工作。别这样。从pthread或
std::mutex
使用适当的互斥对象(如果是C++1x)。@如果使用std::mutex,我应该将mutex.lock()放在哪里?请参阅上面的注释代码,我尝试了它,但没有成功,因为它在两个类中是互斥的。不要使用<