Форум программистов, компьютерный форум, киберфорум
C/C++: WinAPI
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.70/30: Рейтинг темы: голосов - 30, средняя оценка - 4.70
242 / 120 / 14
Регистрация: 15.10.2010
Сообщений: 395
1

Сколько потоков можно создать?

30.04.2011, 07:24. Показов 5709. Ответов 7
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Работаю над задачей "производитель - потребитель". Задание синхронизировать потоки. Всё вроде сделал и получилось. При небольшом количестве потоков работает отлично. Но когда хочу создать около 100 потоков(ну около 100 производителей и 100 потребителей), синхронизация не работает. Может есть какое то ограничение на создание потоков в рамках одного процесса?
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
30.04.2011, 07:24
Ответы с готовыми решениями:

Замерить сколько потоков завершится, запуская их случайным образом
Требования: Использование только вызовов API. Задание: Создать 5 потоков приостановленными. Внутри...

Область видимости общей переменной для потоков + закрытие потоков
Есть два вопроса про потоки. Первый. Как можно сделать общую переменную для основного потока и...

Сколько можно создать потоков исходя из количества процессоров и объема оперативной памяти?
Как понять, сколько можно создать потоков исходя из количества процессоров и объема оперативной...

О потоках std::thread: можно ли вложить потоки друг в друга и можно ли создать динамический массив потоков?
1) Могу ли я вложить потоки друг в друга? 2) Могу ли я создать динамический массив потоков,...

7
374 / 321 / 32
Регистрация: 24.02.2011
Сообщений: 1,512
Записей в блоге: 1
30.04.2011, 11:51 2
Вообще говорят о 2000. Связано это с тем, что по умолчанию на каждый поток резервируется 1МБ под стек. Что в итоге дает около 2 ГБ, которыми ограничивается размер доступной памяти из user-mode приложений в 32-разрядных системах (опять же по умолчанию).
1
242 / 120 / 14
Регистрация: 15.10.2010
Сообщений: 395
30.04.2011, 12:47  [ТС] 3
Может я чего то не правильно сделал? Хотя при малом количестве потоков всё работает.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
#include <stdlib.h>
#include <stdio.h>
#include <conio.h>
#include <windows.h>
#include <time.h>
//#include <iostream>
#define BufferSize 5
#define Producers 10
#define Consumers 15
//  using namespace std;
DWORD WaitProducer;//ïåðåìåííûå ïîìîãóò îïðåäåëèòü,
bool Trans;        // çàêîí÷èëè ëè ðàáîòó ïèñàòåëè
int Buffer[BufferSize];
HANDLE hFull, hEmpty, hMutex;
 
DWORD WINAPI Producer(void * pValue)  // ïðîöåäóðà îòâ çà ðàáîòó ïèñàòåëåé
{
 int SleepInterval, Value, i, Count, Written;
 Trans = true;   
 srand(time(NULL));
 Count = 15;//êàæäûé ïèñàòåëü ñîâåðøàåò 15 çàïèñåé
 while (Count>0)
 {
       Count--;
       
       Value = rand()%1000+1;
       WaitForSingleObject(hEmpty, INFINITE);//æäåì, åñëè áóôåð ïåðåïîëíåí
       WaitForSingleObject(hMutex, INFINITE);//æäåì, åñëè çàíÿò
       //cout << "\n\nValue = " << Value << endl;
       if (Buffer[BufferSize-1]!=0)//åñëè ïîñëåäíèé ýëåìåíò íå íîëü, òî îøèáêà
           printf("Producer: %d | Value %d losted\n", Value, Buffer[BufferSize-1]);
       else
           printf("Producer: %d\n\n\n", Value);
       for (i=BufferSize-2; i >= 0; i--)//ñäâèãàåì áóôåð, îñòàâëÿÿ äëÿ çàïèñè ïåðâóþ ÿ÷åéêó
           Buffer[i+1]=Buffer[i];
       Buffer[0]=Value;//ïèøåì â íå¸ Value
       ReleaseSemaphore(hMutex, 1, NULL);//îñâîáîæäàåì äîñòóï ê áóôåðó
       ReleaseSemaphore(hFull, 1, NULL);//óâåëè÷èâàåì ñ÷åò÷èê äîñòóïíûõ äàííûõ
       SleepInterval=rand()%2000+20000;
       Sleep(SleepInterval);//îòêàçûâàåìñÿ îò îñòàòêà êâàíòà âðåìåíè è æäåì SleepInterval ìñ
 }
 return 0;
}
 
DWORD WINAPI Consumer(void * pValue)// ïðîöåäóðà îòâ çà ðàáîòó ÷èòàòåëåé
{
  int SleepInterval, Value, i, Count, Written;
  while(Trans)
  {
      Written=0;
      /*â áåñêîíå÷íîì öèêëå ïðîâåðÿåì íå çàêîí÷èëè ëè ñâîþ ðàáîòó ïèñàòåëè
      Åñëè íåò, òî æäåì íàëè÷èÿ äàííûõ â áóôåðå 200ìñ. Åñëè ïîÿâèëèñü äàííûå,
      òî ïðîäîëæàåì ðàáîòó, åñëè æå íåò, âûïîëíÿåì ïðîâåðêó ñíîâà*/
      while(1)
      {
          if(Trans)
          {
               WaitProducer = WaitForSingleObject(hFull, 200);
               if(WaitProducer == WAIT_OBJECT_0)
                   break;
          }
          else
               return 0;
      }
      WaitForSingleObject(hMutex, INFINITE);//æäåì äîñòóïà ê áóôåðó
      for (i=BufferSize-1; i>=0; i--)//÷èòàåì ïåðâûé äîñòóïíûé ýëåìåíò ñ êîíöà
          if (Buffer[i]!=0)
          {
              Written=i;
              break;
          }
      Value=Buffer[Written];
      Sleep(rand()%21);
      Buffer[Written]=0;//îáíóëÿåì ñ÷èòàííóþ ÿ÷åéêó
      if (Value==0)
          printf("\t\t\t\tConsumer: %d | The value is wrong!\n", Value);
      else
          printf("\t\t\t\tConsumer: %d\n", Value);
      ReleaseSemaphore(hMutex, 1, NULL);
      ReleaseSemaphore(hEmpty, 1, NULL);
      SleepInterval=rand()%2000+1000;
      Sleep(SleepInterval);
  }
  return 0;
}
 
int main()
{
    HANDLE hThreads[Producers+Consumers];
    DWORD ThreadId;
    int i;
    srand(time(NULL));
    /*ñåìàôîð îáåñïå÷èâàåò ìîíîïîëüíûé äîñòóï ê áóôåðó.
    Èìååò ìàêñèìàëüíîå çíà÷åíèå 1, ëþáîé ïîòîê, ïîëó÷àÿ äîñòóï ê áóôåðó, îáíóëÿåò
    ñ÷åò÷èê ÷èñëà ðåñóðñîâ, òåì ñàìûì çàïðåùàÿ è ÷èòàòåëÿì è ïèñàòåëÿì äîñòóï ê áóôåðó*/
    hMutex=CreateSemaphore(NULL, 1, 1,"Mutex");
    /*íå ïóñêàåò ÷èòàòåëÿ ê áóôåðó, êîãäà îí ïóñò
    èçíà÷àëüíî èíèöèàëèçèðîâàí íóë¸ì. Êàæäûé ïèñàòåëü, çàïèñàâ èíôîðìàöèþ
    â áóôåð, óâåëè÷èâàåò ñ÷åò÷èê ÷èñëà ðåñóðñîâ íà åäèíèöó, òåì ñàìûì ïðåäîñòàâëÿÿ
    äîñòóï ê áóôåðó ÷èòàòåëÿì*/
    hFull=CreateSemaphore(NULL, 0, BufferSize ,"Full");
    /*ñåìàôîð ïðåîäõðàíÿåò îò ïîòåðè äàííûõ â áóôåðå.
    Èçíà÷àëüíî ñ÷åò÷èê èíèöèàëèçèðîâàí ðàçìåðîì áóôåðà
    êàæäûé ïèñàòåëü çàïèñûâàåò â áóôåð ïî îäíîìó çíà÷åíèþ,
    ïðè ýòîì âû÷èòàåò èç ñ÷åò÷èêà 1. Êîãäà áóôåð çàïîëíåí, äî êîíöà
    íè îäèí ïèñàòåëü íå ìîæåò ïîëó÷èòü ê íåìó äîñòóï, è áóäåò îæèäàòü, ïîêà
    õîòÿ áû îäèí èç ÷èòàòåëåé íå ïðî÷òåò ÷èñëî èç áóôåðà è íå óâåëè÷èò
    ñåìàôîð íà åäèíèöó*/
    hEmpty=CreateSemaphore(NULL, BufferSize, BufferSize,"Empty");
 
    for (i=0; i<BufferSize; i++) Buffer[i]=0;  //îáíóëÿåì áóôåð
 
    //ñîçäàåì ïîòîêè ñ ôóíêöèÿìè ÷èòàòåëåé è ïèñàòåëåé
    for (i=0; i<Producers; i++)
        hThreads[i]=CreateThread(0, 0, Producer, 0,0, &ThreadId);
 
    for (i=Producers; i<Producers+Consumers; i++)
        hThreads[i]=CreateThread(0, 0, Consumer, 0, 0, &ThreadId);
 
    WaitForMultipleObjects(Producers, hThreads, true, INFINITE);//æä¸ì çàâåðøåíèÿ ðàáîòû ïèñàòåëåé
    Trans=false;//ñèãíàë î òîì, ÷òî ïèñàòåëè çàêîí÷èëè ðàáîòó
    /*æä¸ì çàâåðøåíèÿ ðàáîòû ÷èòàòåëåé*/
    WaitForMultipleObjects(Producers+Consumers, hThreads, true, INFINITE);
    //çàêðûâàåì äåñêðèïòîðû ïîòîêîâ è ñåìàôîðîâ
    for (i=0; i<Producers+Consumers; i++)
        CloseHandle(hThreads[i]);
    CloseHandle(hMutex);
    CloseHandle(hFull);
    CloseHandle(hEmpty);
    system("PAUSE");
    return 0;
}
Смысл таков: создается Producers потоков производителей, и Consumers потоков потребителей. Производители записывают в буфер одно число, потребитель отттуда его считывает (и удаляет после считывания. Цель: синхронизировать потоки так, чтобы не было потери данных из буфера, чтобы доступ к нему был монопольным, и чтобы если буфер пуст, доступ читателям блокировался.
Я решил эту задачу с помощью трёх семафоров. Описание их есть в комментариях программы.
Посмотрите, может что не так? А то голову уже сломал.О_о
0
1487 / 1414 / 240
Регистрация: 19.02.2010
Сообщений: 3,915
07.05.2011, 23:52 4
RUSya82 при росте числа потоков может число дескрипторов в системе превысить некоторый порог. На каждый объект ядра (кроме, вроде бы, критической секции? не помню, что там у Рихтера было написано) заводится дескриптор, плюс на каждый поток, который что-то выводит на экран, тоже заводится один или два дескриптора (при выводе через функции gdi дескрипторы точно заводятся, может быть, и при выводе на консоль тоже такая бяка происходит).

Ну и надо с помощью диспетчера задач (при том числе потоков в проге, когда прога ещё не разваливается) посмотреть - не растёт ли при работе проги со временем число потоков и число дескрипторов. Это для гарантии, что закрываете-удаляете все ранее инициализированные объекты ядра.

Ну а четко ограничения могут быть обозначены-описаны либо в МСДН, либо в книге Рихтера, либо у Руссиновича-Соломона (в книге про потроха Винды). Всё это есть в электронном виде.
1
Brainsbreaker
899 / 374 / 54
Регистрация: 01.02.2011
Сообщений: 1,608
08.05.2011, 19:08 5
Руссинович-Соломон, да, хорошая книга, про потроха... )
0
242 / 120 / 14
Регистрация: 15.10.2010
Сообщений: 395
12.05.2011, 07:26  [ТС] 6
Цитата Сообщение от VTsaregorodtsev Посмотреть сообщение
. На каждый объект ядра (кроме, вроде бы, критической секции? не помню, что там у Рихтера было написано) заводится дескриптор
Насколько я помню, на каждый объект ядра заводится дескриптор, просто критическая секция таковым не является.
0
111 / 112 / 18
Регистрация: 11.03.2011
Сообщений: 421
13.05.2011, 00:04 7
тоже читал где-то о предельно допустимом количестве дескрипторов в системе.

собственно, практиковал создавать указанное пользователем количество потоков для параллельной обработки. пробовал 90 потоков одновременно запускать. у системы инфаркт чуть не случился =)

по поводу семафоров: на мсдн-е (в документации) написана рекомендация семафоры не использовать, а заменить их ивентами, при чем обрабатывать состояния вручную.

и как на счет посмотреть в дэбаге возвращаемые значения?

или загнать всё в try {} блоки и проверять все возвращаемые значения, в качестве кидаемого значения, например, счетчик цикла с минусом вписать, а в catch {} еще и код ошибки куда-нибудь записывать.
код ошибки через GetLastError() можно посмотреть.
1
242 / 120 / 14
Регистрация: 15.10.2010
Сообщений: 395
15.05.2011, 12:52  [ТС] 8
Цитата Сообщение от resource2008 Посмотреть сообщение
по поводу семафоров: на мсдн-е (в документации) написана рекомендация семафоры не использовать, а заменить их ивентами, при чем обрабатывать состояния вручную.
Просто я не представляю, как в данном случае контролировать переполнение и опустошение буфера с помощью событий? А если ёмкость буфера не 2, а 20? Для этого как раз и есть специально обученный зверь - семафор, у которого имеется счетчик числа ресурсов.
0
15.05.2011, 12:52
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
15.05.2011, 12:52
Помогаю со студенческими работами здесь

Как определять, сколько максимально потоков можно запускать?
Здравствуйте. Есть класс. Он накапливает в себе задания на отправку запросов, а потом разом,...

Создать столько же потоков, сколько строк в List
Всем привет! Понадобилось написать программку которая посылает запрос и с ним текст из блокнота Я...

Можно ли создать на одном сокете одновременно много потоков
Привет всем. Читаю о потоках, но не до конца понимаю их логику, поэтому хочу попросить кого-небудь...

Сколько маркеров можно создать на карте
Здравствуйте. Задался вопросом, сколько можно маркеров создать на гугл карте, чтобы она не...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
8
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru