Проблема с потоками

Тема в разделе "WASM.WIN32", создана пользователем SysProger, 20 мар 2008.

  1. SysProger

    SysProger New Member

    Публикаций:
    0
    Регистрация:
    18 июл 2007
    Сообщения:
    127
    В одном приложении не могу создать более 1000 потоков. Причём эта перегрузка по количеству потоков влияет на ОС (возможно переполнение памяти или идентификаторов потоков).
    Допустим, я создаю 800 потоков. После завершения их работы мне нужно провести чистку памяти, а потом опять запустить 800 потоков. Весь вопрос в том, какую именно память нужно очистить.
     
  2. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    Невероятно. Зачем стока потоков, ведь они скорость не увеличат.
    Начёт памяти - надо только память выделенную под стек освободить.
     
  3. wsd

    wsd New Member

    Публикаций:
    0
    Регистрация:
    8 авг 2007
    Сообщения:
    2.824
    Clerk
    мож у него сервак с потоком на каждый коннект
     
  4. asmfan

    asmfan New Member

    Публикаций:
    0
    Регистрация:
    10 июл 2006
    Сообщения:
    1.004
    Адрес:
    Abaddon
    SysProger, Clerk
    Это что за новость про освобождение чего-то там после завершения потока? Ну да, хэндл надо бы закрыть поточный, а что освобождать то ещё? Какие-то новые теории тут слышу...
     
  5. Ursus

    Ursus Member

    Публикаций:
    0
    Регистрация:
    15 мар 2006
    Сообщения:
    238
    Адрес:
    Russia
    Хочется надеяться, что нет :)
     
  6. wasm_test

    wasm_test wasm test user

    Публикаций:
    0
    Регистрация:
    24 ноя 2006
    Сообщения:
    5.582
    Код (Text):
    1. DWORD WINAPI thread(LPVOID)
    2. {
    3.     return 0;
    4. }
    5.  
    6. int main()
    7. {
    8.     for (int i=0; i<100000; i++)
    9.     {
    10.         HANDLE hTH = CreateThread (0, 0, thread, 0, 0, 0);
    11.         if (!hTH)
    12.         {
    13.             printf("Cannot create thread %d\n", i);
    14.         }
    15.         CloseHandle(hTH);
    16.     }
    17.     printf("ok\n");
    18.     return 0;
    19. }
    нормально отрабатывает и ниче освобождать не надо
     
  7. SysProger

    SysProger New Member

    Публикаций:
    0
    Регистрация:
    18 июл 2007
    Сообщения:
    127
    Clerk, wsd
    Программу пишу в образовательных целях.

    Поясняю.
    Открываю свою прогу в task manager, там вижу следующее: "Число дескрипторов - 185517". Т.е. функция ExitThread не может уменьшить это число. А памяти уже недостаточно для дальнейшего запуска любого потока. Потоки других программ тоже запускаться не смогут до завершения моего приложения. Вот мне и нужно узнать, как выйти из этой ситуации, не завершая моего приложения.
     
  8. wsd

    wsd New Member

    Публикаций:
    0
    Регистрация:
    8 авг 2007
    Сообщения:
    2.824
    Ursus

    ИМХО: распространённая техника...
    А вы больше сполинг предпочитаете?
     
  9. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    SysProger
    Ес-но, т.к.
     
  10. SysProger

    SysProger New Member

    Публикаций:
    0
    Регистрация:
    18 июл 2007
    Сообщения:
    127
    Great
    В твоей программе потокам мало дано шансов на выполнение. Ведь как только ты его создаёшь, ты сразу же закрываешь его описатель.
     
  11. SysProger

    SysProger New Member

    Публикаций:
    0
    Регистрация:
    18 июл 2007
    Сообщения:
    127
    leo
    Ну поставлю я "CloseHandle(GetCurrentThread())" вместо "return 0" в теле потока, но делу этим не поможешь.
     
  12. SSS

    SSS New Member

    Публикаций:
    0
    Регистрация:
    24 ноя 2003
    Сообщения:
    12
    SysProger
    ИМХО, вы по моему вообще не понимаете о чем говорите.
    GetCurrentThread() - возвращает псевдоописатель, а CloseHandle закрывает реальный описатель.
    Читайте внимательее пост leo и факинг мануал.

    А вообще, предельное кол-во потоков, которое вы сможее создать в рамках своего процесса, зависеть будет от доступной памяти и размера стека, которое выделяется на поток по умолчанию. Создать их можно хоть 25 тыс.. только смысла в этом нет никакого.
     
  13. wasm_test

    wasm_test wasm test user

    Публикаций:
    0
    Регистрация:
    24 ноя 2006
    Сообщения:
    5.582
    от того, что я закрываю описатель, поток не уничтожается. rtfm


    UPD:
    Код (Text):
    1. LONG j = 0;
    2.  
    3. DWORD WINAPI thread(LPVOID)
    4. {
    5.     InterlockedIncrement (&j);
    6.     return 0;
    7. }
    8.  
    9. int main()
    10. {
    11.     for (int i=0; i<100000; i++)
    12.     {
    13.         HANDLE hTH = CreateThread (0, 0, thread, 0, 0, 0);
    14.         if (!hTH)
    15.         {
    16.             printf("Cannot create thread %d\n", i);
    17.         }
    18.         CloseHandle(hTH);
    19.     }
    20.     printf("ok, j=%d\n", j);
    21.     return 0;
    22. }
    Вывод: ok, j=99996
    (последние 4 потока не успевают отработать, поскольку программа преждевременно завершается. если перед printf(ok) воткнуть Sleep(100) тогда все сойдется)

    Объект имеет два счетчика ReferenceCount и HandleCount.
    Первый инкрементируется, когда кто-то хочет использовать явный указатель на объект,
    а когда хотят открыть хендл на него, то инкрементируются оба.
    ReferenceCount >= HandleCount всегда; объект удаляется, если он не permament и если ReferenceCount==0

    Так что закрытие хендла еще не влечет завершение потока
     
  14. rpy3uH

    rpy3uH New Member

    Публикаций:
    0
    Регистрация:
    14 сен 2006
    Сообщения:
    503
    ты посчитай сколько памяти будет выделено толкьо для стека каждого потока. По-умолчанию размер стека равен 1 МБ. 1000 потоков - 1000 МБ! и это только для стека.
     
  15. wasm_test

    wasm_test wasm test user

    Публикаций:
    0
    Регистрация:
    24 ноя 2006
    Сообщения:
    5.582
    rpy3uH
    стек очень хитро устроен. мало того, что винда никогда не передает физические страницы памяти до первого обращения к виртуальному адресу, так еще и стек делается разрастающимся с помощью PAGE_GUARD.
    так что реально памяти расходуется на порядки меньше
     
  16. n0name

    n0name New Member

    Публикаций:
    0
    Регистрация:
    5 июн 2004
    Сообщения:
    4.336
    Адрес:
    Russia
    разервируется может метр, а коммитится меньше
     
  17. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    asmfan
    Ага, а из ThreadRoutine управление куда передаётся и что происходит по команде ret или как выполняется ExitThread ?
    Если поток завершать через ZwTerminateThread, то память под TEB освобождать не надо, а вот под стек - придётся.
     
  18. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    Clerk
    Повторяем матчасть: Стек не освобождается только при выходе по (Zw)TerminateThread, поэтому эту "бяку" нужно использовать только в крайнем случае. При нормальном выходе по ret или ExitThread система сама освобождает память под стек
     
  19. asmfan

    asmfan New Member

    Публикаций:
    0
    Регистрация:
    10 июл 2006
    Сообщения:
    1.004
    Адрес:
    Abaddon
    Clerk
    Вообще да, правы. По ExitThread вызывается RtlFreeThreadActivationContextStack и LdrShutdownThread и происходит много разных вещей, но тут всё на натив апи, а по ret и, собсно, ExitThread ничего делать самому не надо.
    [added]
    leo обогнал на повороте =)
     
  20. n0name

    n0name New Member

    Публикаций:
    0
    Регистрация:
    5 июн 2004
    Сообщения:
    4.336
    Адрес:
    Russia
    leo
    ret фактически возвращает управлению коду который сам вызовет ExitThread. Если создать поток с использованием NtCreateThread тогда ret вернет в никуда.