c++ многопоточность, нужна помощь с синхронизацией

Discussion in 'С/С++, C#, Rust, Swift, Go, Java, Perl, Ruby' started by aladin1, 22 Jun 2015.

  1. aladin1

    aladin1 Member

    Joined:
    16 Sep 2009
    Messages:
    330
    Likes Received:
    29
    Reputations:
    7
    в 20 потоков работает норм, если сделать 100 и более - вылет на старте. Смысл таков: Читаем строки с адресами в вектор, затем дёргаем потоками строки из вектора и затем передаем для работы сокету, покуда не считаем каждую строку вектора.
    Code:
    #include "stdafx.h"
    #define WIN32_LEAN_AND_MEAN
    #include <windows.h>
    #include <process.h>
    #include <iostream>
    #include <fstream>
    #include <vector>
    #include <string>
    using namespace std;
    #define THREADS_NUMBER 100
    int a = 0;
    CRITICAL_SECTION cs;
    DWORD WINAPI ThreadFunc(LPVOID lpParametr){
        vector<string> * ips = (vector<string> *)lpParametr;
        char ip[16];
        bool end = 0;
        EnterCriticalSection( &cs );
        if ( a >= ips->size() ) end = 1;
        LeaveCriticalSection( &cs );
        if (end) return 1;
        for ( ; ; ){
            EnterCriticalSection( &cs );
            string ip2 = ( *ips )[a];
            strcpy( ip, ip2.c_str() );
            cout << ip << "\n";
            a++;
            if ( a >= ( ips->size() ) ) end = 1;
            LeaveCriticalSection( &cs );
            if (end) break;
            }
            // далее работа сокета c полученной ip
       
        return 0;
    }
    int main()
    {  
        vector <string> ips;
        fstream fs_ips;
        fs_ips.open( "ips.txt" );
        while ( !fs_ips.eof() ) {
            char ip2[16];
            fs_ips >> ip2;
            ips.push_back( ip2 );
        }
        fs_ips.close();
        HANDLE * p_hThreads = new HANDLE [THREADS_NUMBER];
        InitializeCriticalSection (&cs);
        for( int i = 0; i < THREADS_NUMBER; ++i)
        {
            p_hThreads[i] = CreateThread(NULL, 0, ThreadFunc, &ips, 0, NULL);
        }
        WaitForMultipleObjects( THREADS_NUMBER, p_hThreads, TRUE, INFINITE );
        DeleteCriticalSection (&cs);
        for( int i = 0; i < THREADS_NUMBER; ++i)
        {
            CloseHandle(p_hThreads[i]);
        }
        system("pause");
    }
     
  2. St0nX

    St0nX Elder - Старейшина

    Joined:
    19 May 2007
    Messages:
    257
    Likes Received:
    46
    Reputations:
    0
    Толку от твоих 100 потокотов никакого нету. У тебя в коде лютая гонка и куча вариантов как получить рейс кондишин. Сделай тредпул и сабмить туда таски зачем себя так ненавидеть.
     
  3. aladin1

    aladin1 Member

    Joined:
    16 Sep 2009
    Messages:
    330
    Likes Received:
    29
    Reputations:
    7
    мало что понял из сказанного, добавлю - пишу это для парсинга ответов от pop-серверов
     
  4. St0nX

    St0nX Elder - Старейшина

    Joined:
    19 May 2007
    Messages:
    257
    Likes Received:
    46
    Reputations:
    0
    Что такое тред пул:
    https://en.wikipedia.org/wiki/Thread_pool_pattern
    имплементации:
    boost::threadpool
    Велосипед с хабра: http://habrahabr.ru/post/188234/
    https://github.com/progschj/ThreadPool

    ЗЫ: Если нужно, лишь бы работало, сделай однопоточное приложение, не мучайся. Если уж нет, то начни с изучения архитектуры многопоточных приложений.
     
    aladin1 likes this.
  5. vladzzag

    vladzzag New Member

    Joined:
    5 Jul 2015
    Messages:
    4
    Likes Received:
    0
    Reputations:
    0
    Фигасе.. 100 тредов? Чувак, это слишком много.. ;)
     
  6. GRRRL Power

    GRRRL Power Elder - Старейшина

    Joined:
    13 Jul 2010
    Messages:
    823
    Likes Received:
    185
    Reputations:
    84
    Библиотека threadpool не входит в Boost. Зато есть boost::thread_group, который, правда, не совсем тред пул. В качестве тред пула можно использовать boost::asio::io_service.
     
  7. Developer™

    Developer™ Member

    Joined:
    7 Nov 2013
    Messages:
    30
    Likes Received:
    6
    Reputations:
    0
    А нахрена тебе 100 потоков? Думаешь, чем больше - тем лучше? Максимально рекомендуемое количество потоков - количество процессоров/ядер * 2. В идеале вообще без умножения. А все эти овер100500 никому не упали. Правильно сказали тебе - пул используй! Вообще, я уже как-то говорил что надо увеличивать не количество потоков, а количество работы выполняемой потоком.
     
  8. Jingo Bo

    Jingo Bo Member

    Joined:
    25 Oct 2009
    Messages:
    368
    Likes Received:
    51
    Reputations:
    7
    Порглядел бегло код, проблем с синхронизацией у тебя нет. Есть один нюанс, апишная функция
    WaitForMultipleObjects если не ошибаюсь может ожидать до 64 дескрипторов, так что 100 не покатит. Здесь нужно создать объект события и когда обработка в потоках заканчивается - его устанавливать, а в main событие ждать.
     
  9. Developer™

    Developer™ Member

    Joined:
    7 Nov 2013
    Messages:
    30
    Likes Received:
    6
    Reputations:
    0
    Раз уж ТС-у так надо 100 потоков - посоветую использовать std::thread -> joinable -> join. Но 100 потоков.. явно не здоровая хрень