使用单独的互斥锁进行pop和push操作std :: queue而不是一个

时间:2015-07-26 12:14:30

标签: c++ multithreading stl locking

假设有一个生产者和多个消费者并且他们使用std::queue,为了保护std::queue中的数据,访问此std::queue时必须使用互斥锁。

但是使用两个单独的锁呢?一个用于pop,一个用于push?我认为使用两个单独的锁可能会更快。

我查看了STL源代码。 std::queue默认情况下由std::deque实施。 pop_front()push_back()使用两个单独的迭代器来访问数据,一个用于第一个元素,一个用于最后一个元素。

void push_front(const value_type& __x){
    if (this->_M_impl._M_start._M_cur != this->_M_impl._M_start._M_first){
        this->_M_impl.construct(this->_M_impl._M_start._M_ur - 1, __x);
    } else {
        _M_push_front_aux(__x);
    }
}

void push_back(){
    if (this->_M_impl._M_finish._M_cur != this->_M_impl._M_finish._M_first){
        this->_M_impl.construct(this->_M_impl._M_finish._M_ur - 1, __x);
    } else {
        _M_pop_back_aux();
    }
}

因此,当一个线程pop队列时,另一个线程切入并尝试push_back。因为这两个操作使用不同的迭代器,它们指向deque的两个不同的端点,所以看起来这两个操作都可以正常吗?

1 个答案:

答案 0 :(得分:1)

# -*- coding: utf-8 -*- import iopro from pandas import * neuro = DataFrame() cardio = DataFrame() cancer = DataFrame() addiction = DataFrame() Adrugs = DataFrame() Mdrugs = DataFrame() Vdrugs = DataFrame() all_drugs = DataFrame() for year in xrange(2005,2013): for month in xrange(1,13): if year == 2005 and month < 7: continue filename = 'PATH/lmed_' + str(year) + '_mon'+ str(month) +'.txt' adapter = iopro.text_adapter(filename,parser='csv',field_names=True,output='dataframe',delimiter='\t') monthly = adapter[['LopNr','ATC','TKOST']][:] monthly['year']=year monthly['month']=month neuro = neuro.append(monthly[(monthly.ATC.str.startswith('N')) & (~(monthly.TKOST.isnull()))]) cardio = cardio.append(monthly[(monthly.ATC.str.startswith('C')) & (~(monthly.TKOST.isnull()))]) cancer = cancer.append(monthly[(monthly.ATC.str.startswith('L')) & (~(monthly.TKOST.isnull()))]) addiction = addiction.append(monthly[(monthly.ATC.str.startswith('N07')) & (~(monthly.TKOST.isnull()))]) Adrugs = Adrugs.append(monthly[(monthly.ATC.str.startswith('A')) & (~(monthly.TKOST.isnull()))]) Mdrugs = Mdrugs.append(monthly[(monthly.ATC.str.startswith('M')) & (~(monthly.TKOST.isnull()))]) Vdrugs = Vdrugs.append(monthly[(monthly.ATC.str.startswith('V')) & (~(monthly.TKOST.isnull()))]) all_drugs = all_drugs.append(monthly[(~(monthly.TKOST.isnull()))]) del monthly all_drugs = all_drugs.groupby(['LopNr','year','month']).sum() all_drugs = all_drugs.astype(int,copy=False) all_drugs.to_csv('PATH/monthly_all_drugs_costs.csv') del all_drugs neuro = neuro.groupby(['LopNr','year','month']).sum() neuro = neuro.astype(int,copy=False) neuro.to_csv('PATH/monthly_neuro_costs.csv') del neuro cardio = cardio.groupby(['LopNr','year','month']).sum() cardio = cardio.astype(int,copy=False) cardio.to_csv('PATH/monthly_cardio_costs.csv') del cardio cancer = cancer.groupby(['LopNr','year','month']).sum() cancer = cancer.astype(int,copy=False) cancer.to_csv('PATH/monthly_cancer_costs.csv') del cancer addiction = addiction.groupby(['LopNr','year','month']).sum() addiction = addiction.astype(int,copy=False) addiction.to_csv('PATH/monthly_addiction_costs.csv') del addiction Adrugs = Adrugs.groupby(['LopNr','year','month']).sum() Adrugs = Adrugs.astype(int,copy=False) Adrugs.to_csv('PATH/monthly_Adrugs_costs.csv') del Adrugs Mdrugs = Mdrugs.groupby(['LopNr','year','month']).sum() Mdrugs = Mdrugs.astype(int,copy=False) Mdrugs.to_csv('PATH/monthly_Mdrugs_costs.csv') del Mdrugs Vdrugs = Vdrugs.groupby(['LopNr','year','month']).sum() Vdrugs = Vdrugs.astype(int,copy=False) Vdrugs.to_csv('PATH/monthly_Vdrugs_costs.csv') del Vdrugs select * from( select a.*,'10' as srv from px_conversions_srv10 a union all select b.*,'12' as srv from px_conversions_srv12 b ) as ff where ff.adv_transaction_id in(1333764016); update ff SET ff.`status`=8; 可能在内部访问不同的迭代器,但这就是整个抽象感:你不能确定它,而且不允许依赖它。

而且,正如评论中已经指出的那样,还有pop_front,这是因为需要在push_back中执行C ++ 11。为了满足这一要求,sizeO(1)都需要改变一些内部存储,如果大小,那么你肯定会有竞争条件。

然后想想当你的队列变空时会发生什么......

简而言之:不要这样做。要在并发设置中使用push_back,您需要一个互斥锁来保护它。

作为替代方案,您应该研究无锁数据结构。