Boost::Mutex в классе не является потокобезопасным

Я изучаю параллельное программирование, и я хочу создать класс, в котором каждый объект отвечает за запуск собственного Boost:Thread. Я немного запутался с этим кодом, потому что он использует МНОГО функций, которые мне не очень удобны (динамически выделяемая память, указатели функций, параллелизм и т. д. и т. д.). Как и в каждой строке кода, мне приходилось проверять некоторые ссылки, чтобы сделать это правильно.

(Да, в реальном коде учитывается вся выделенная память!)

У меня проблемы с мьютексами. Я объявляю его статическим, и кажется, что он получает одинаковое значение для всех экземпляров (как и должно быть). Код ВСЕ ЕЩЕ не потокобезопасен.

Мьютекс должен остановить потоки (правильно?) от дальнейшего продвижения в случае, если кто-то другой заблокировал его. Поскольку мьютексы ограничены (своего рода изящная функциональность), и это внутри оператора if, который должен искать другие потоки, нет? Тем не менее я получаю консольные выходы, которые явно предполагают, что это не потокобезопасно.

Также я не уверен, что использую static vaiable right. Я пробовал разные способы ссылаться на него (Seller::ticketSaleMutex), но единственное, что сработало, это «this->ticketSaleMutex», что кажется очень сомнительным и, кажется, противоречит цели его статичности.

Продавец.ч:

class Seller
{
public:     
    //Some vaiables
private:
    //Other variables
    static boost::mutex ticketSaleMutex;      //Mutex definition
};

Продавец.cpp:

boost::mutex Seller::ticketSaleMutex;         //Mutex declaration

void Seller::StartTicketSale()
{
    ticketSale = new boost::thread(boost::bind(&Seller::SellTickets, this));

}
void Seller::SellTickets()
{
    while (*totalSoldTickets < totalNumTickets)
    {
        if ([Some time tick])
        {
            boost::mutex::scoped_lock(this->ticketSaleMutex);
            (*totalSoldTickets)++;
            std::cout << "Seller " << ID << " sold ticket " << *totalSoldTickets << std::endl;
        }

    }
}

основной.cpp:

int main(int argc, char**argv)
{
    std::vector<Seller*> seller;
    const int numSellers = 10;
    int numTickets = 40;
    int *soldTickets = new int;
    *soldTickets = 0;
    for (int i = 0; i < numSellers; i++)
    {
        seller.push_back(new Seller(i, numTickets, soldTickets));
        seller[i]->StartTicketSale();
    }
}

person Sebastian Zander    schedule 24.07.2012    source источник
comment
Seller::ticketSaleMutex определенно должно работать. Это полностью эквивалентно this->ticketSaleMutex.   -  person rodrigo    schedule 25.07.2012
comment
ошибка C2655: «Seller::ticketSaleMutex»: определение или повторное объявление недопустимы в текущей области + ошибка C2371: «ticketSaleMutex»: переопределение; различные основные типы   -  person Sebastian Zander    schedule 25.07.2012
comment
Это очевидно, потому что я делаю это неправильно, это работает, когда я правильно использую мьютексы (как в ответе)   -  person Sebastian Zander    schedule 25.07.2012


Ответы (1)


Это создаст временный объект, который будет немедленно уничтожен:

boost::mutex::scoped_lock(this->ticketSaleMutex);

в результате нет синхронизации. Вам нужно объявить переменную:

boost::mutex::scoped_lock local_lock(this->ticketSaleMutex);
person hmjd    schedule 24.07.2012
comment
Оставляя вас со всеми накладными расходами на блокировку мьютекса, без каких-либо преимуществ синхронизации. Ой. - person tmpearce; 25.07.2012
comment
О, это было так просто :D Просто показывает, что мне нужно практиковать одну вещь за раз, иначе это просто сбивает с толку. Эта единственная строка кода содержала 3 вещи, которые я никогда раньше не использовал: указатель this, указатели функций (ну, очевидно, потому что я использую указатель this) и параллелизм. - person Sebastian Zander; 25.07.2012
comment
Поскольку ticketSaleMutex равно static, вы также используете Seller::ticketSaleMutex. Что, IMO, более понятно, поскольку this-> делает его похожим на переменную экземпляра (нестатическую). - person hmjd; 25.07.2012
comment
Да, но при этом я получаю ошибку компилятора: error C2371: 'ticketSaleMutex' : redefinition; различные основные типы - person Sebastian Zander; 25.07.2012
comment
Это очевидно, потому что я делаю это неправильно, это работает, когда я правильно использую мьютексы (как в ответе) - person Sebastian Zander; 25.07.2012
comment
Это правильный способ обратиться к члену класса static. Например, см. ideone.com/8h6iu. - person hmjd; 25.07.2012
comment
В контексте метода-члена статические переменные не нуждаются в разрешении своей области путем разыменования this или путем добавления к ним оператора разрешения области видимости. В любом методе-члене класса Seller вы можете просто напрямую обратиться к статической переменной по имени: boost::mutex::scoped_lock foo(ticketSaleMutex); - person phonetagger; 25.07.2012