Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.60/5: Рейтинг темы: голосов - 5, средняя оценка - 4.60
0 / 0 / 1
Регистрация: 26.10.2016
Сообщений: 130

Критическая секция не работает

19.04.2017, 20:20. Показов 1178. Ответов 14
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Значение переменной становится равно не нулю даже при наличии критических секций. Почему?

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
#include <iostream>
#define _AFXDLL
#include <afxwin.h>
 
using namespace std;
 
int i;
CRITICAL_SECTION critsect;
 
void threadFunc(void *) {
    i++;
    Sleep(10000);
    i--;
 
}
 
void threadFuncWithSync(void *) {
    EnterCriticalSection(&critsect);
    threadFunc(NULL);
    LeaveCriticalSection(&critsect);
}
 
int main() {
    cout << "Without synchronization" << endl;
        _beginthread(threadFunc, 1024, NULL);
        _beginthread(threadFunc, 1024, NULL);
        _beginthread(threadFunc, 1024, NULL);
        _beginthread(threadFunc, 1024, NULL);
        cout << "i = " << i << endl;
 
        i = 0;
        cout << "With synchronization" << endl;
        InitializeCriticalSection(&critsect);
        _beginthread(threadFuncWithSync, 1024, NULL);
        _beginthread(threadFuncWithSync, 1024, NULL);
        _beginthread(threadFuncWithSync, 1024, NULL);
        _beginthread(threadFuncWithSync, 1024, NULL);
 
    cout << "i = " << i << endl;
    system("pause");
    return 0;
}
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
19.04.2017, 20:20
Ответы с готовыми решениями:

Критическая секция
Ребята помогите пожалуйста, надо сделать 5 потоков с помощью критической секции, незнаю как!!! пытался что-то сделать но ничего путного не...

Потоки и критическая секция!
Почему потоки проходят 14 раз, а не 10, как указано в MaxCount?????? Помогите с ответом пожалуйста! Написать программу, главный...

Есть ли критическая секция в стандартной библиотеке?
Здравствуйте! Собственно, сам вопрос. Как использовать критическую секцию в C++? Нашёл информацию о подобном для windows и linux. Есть...

14
Эксперт С++
1675 / 1047 / 174
Регистрация: 27.09.2009
Сообщений: 1,945
19.04.2017, 20:25
i будет равно 0 только после того, как все потоки завершатся. Функция _beginthread только начинает выполнение потока. Печать происходит сразу после того, как все потоки запущены и только-только начали ждать.
0
0 / 0 / 1
Регистрация: 26.10.2016
Сообщений: 130
19.04.2017, 20:29  [ТС]
Nick Alte, а как сделать так, чтобы дождаться окончания потоков и только после этого вывести значение i ?
0
Эксперт С++
1675 / 1047 / 174
Регистрация: 27.09.2009
Сообщений: 1,945
19.04.2017, 20:46
_beginthreadex возвращает дескриптор потока, который можно использовать в функции WaitForSingleObject или WaitForMultipleObjects.
0
0 / 0 / 1
Регистрация: 26.10.2016
Сообщений: 130
19.04.2017, 21:02  [ТС]
Nick Alte, но у меня 4 потока. Как это можно реализовать ? Как каждый раз переводить объект из сигнального в несигнальное состояние ?
0
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
12932 / 6800 / 1820
Регистрация: 18.10.2014
Сообщений: 17,211
19.04.2017, 21:27
Цитата Сообщение от wildnothing Посмотреть сообщение
Как каждый раз переводить объект из сигнального в несигнальное состояние ?
Поток сам себя переводит в правильное состояние. Пока он выполняется - состояние несигнальное. Когда он завершился - сигнальное. Вам надо только подождать его.
0
Эксперт С++
1675 / 1047 / 174
Регистрация: 27.09.2009
Сообщений: 1,945
19.04.2017, 21:28
Не совсем понятен вопрос. Поток сам переводится в состояние "мы дождалися" после того, как его функция завершит работу. Если запустить все потоки, а затем последовательно вызвать WaitForSingleObject на дескрипторе каждого из них, то они будут все завершены. Или можно собрать все дескрипторы в массив и вызвать один раз WaitForMultipleObjects.
0
0 / 0 / 1
Регистрация: 26.10.2016
Сообщений: 130
19.04.2017, 23:30  [ТС]
TheCalligrapher, Nick Alte, вот что у меня вышло:

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
#include <iostream>
#define _AFXDLL
#include <afxwin.h>
 
using namespace std;
 
int i, maxI;
CRITICAL_SECTION critsect;
 
void threadFunc(void *) {
    i++;
    Sleep(10000);
    i--;
    if (i > maxI) maxI = i;
    _endthread();
}
 
void threadFuncWithSync(void *) {
    EnterCriticalSection(&critsect);
    threadFunc(NULL);
    LeaveCriticalSection(&critsect);
    _endthread();
}
 
int main() {
    int n;
    cout << "Without synchronization or with ? 1/2 \n>>";
    cin >> n;
    switch (n) {
    case 1: {
        cout << "Without synchronization" << endl;
        HANDLE t1 = (HANDLE)_beginthread(threadFunc, 1024, NULL);
        HANDLE t2 = (HANDLE)_beginthread(threadFunc, 1024, NULL);
        HANDLE t3 = (HANDLE)_beginthread(threadFunc, 1024, NULL);
        HANDLE t4 = (HANDLE)_beginthread(threadFunc, 1024, NULL);
        WaitForSingleObject(t1, INFINITE);
        WaitForSingleObject(t2, INFINITE);
        WaitForSingleObject(t3, INFINITE);
        WaitForSingleObject(t4, INFINITE);
        break;
    }
    case 2: {
        cout << "With synchronization" << endl;
        InitializeCriticalSection(&critsect);
        HANDLE t1 = (HANDLE)_beginthread(threadFuncWithSync, 1024, NULL);
        HANDLE t2 = (HANDLE)_beginthread(threadFuncWithSync, 1024, NULL);
        HANDLE t3 = (HANDLE)_beginthread(threadFuncWithSync, 1024, NULL);
        HANDLE t4 = (HANDLE)_beginthread(threadFuncWithSync, 1024, NULL);
        WaitForSingleObject(t1, INFINITE);
        WaitForSingleObject(t2, INFINITE);
        WaitForSingleObject(t3, INFINITE);
        WaitForSingleObject(t4, INFINITE);
        break;
    }
    }
    cout << "maxI = " << maxI << endl;
    system("pause");
    return 0;
}
Но теперь во 2 случае с синхронизацией 2, 3 и 4 потоки не завершаются и по сути программа "висит" долгое время. Почему так?
0
Диванный эксперт
Эксперт С++
 Аватар для Max Dark
2550 / 2064 / 971
Регистрация: 09.10.2013
Сообщений: 4,793
Записей в блоге: 4
19.04.2017, 23:36
Цитата Сообщение от wildnothing Посмотреть сообщение
"висит" долгое время. Почему так?
другой поток не может захватить критическую секцию пока ее не освободит первый.
А у вас между захватом и освобождением стоит Sleep(10000);
0
0 / 0 / 1
Регистрация: 26.10.2016
Сообщений: 130
19.04.2017, 23:46  [ТС]
Max Dark, Я убрала _endthread(); и все заработало. Почему?
0
Диванный эксперт
Эксперт С++
 Аватар для Max Dark
2550 / 2064 / 971
Регистрация: 09.10.2013
Сообщений: 4,793
Записей в блоге: 4
19.04.2017, 23:55
Цитата Сообщение от wildnothing Посмотреть сообщение
Почему?
_endthread
_endthread автоматически закрывает дескриптор потока. (Это поведение отличается от API Win32 ExitThread.)
WaitForSingleObject
If this handle is closed while the wait is still pending, the function's behavior is undefined.
Судя по этому - не стоит вызывать _endthread в потоке, если хэндл используется для WaitForSingleObject
0
0 / 0 / 1
Регистрация: 26.10.2016
Сообщений: 130
20.04.2017, 00:22  [ТС]
Max Dark, я делала так же (с _endthread) для потоков без синхронизации и все работало нормально. Не понимаю.
0
Диванный эксперт
Эксперт С++
 Аватар для Max Dark
2550 / 2064 / 971
Регистрация: 09.10.2013
Сообщений: 4,793
Записей в блоге: 4
20.04.2017, 00:42
Цитата Сообщение от wildnothing Посмотреть сообщение
Не понимаю.
Если коротко, то получается что _beginthread/_endthread несовместимы с WaitForSingleObject
Для избежания данной проблемы замените _beginthread на CreateThread
подробнее здесь
Цитата Сообщение от Stack Overflow
If you still want to use the CRTs thread creation functions (_beginthread/_beginthreadex) you should follow these guidelines:
  • Never use the handle returned by _beginthread. With _beginthread the thread handle is automatically closed when the thread exits, which can potentially happen before _beginthread even returns. You can't use it with WaitForSingleObject safely because the thread might have already exited before you call this function. If you want to use the thread handle for anything use _beginthreadex instead.
  • You should never close the handle returned by _beginthread. The CRT will do it automatically, and as described in the previous point, may do so before you have chance to.
  • You should always close the handle returned by _beginthreadex when you no longer need it. The CRT won't do this automatically for you, so it's your own responsibility.
  • Don't call _endthread or _endthreadex unless you want to quickly and abnormally terminate the thread. While the CRT will free its own per thread data, none of the C++ destructors for any of the thread's objects will be called. It behaves similarly to how _exit ends the process without calling destructors.
  • The normal means of ending a thread should be by returning from the function passed as an argument to _beginthread or _beginthreadex. This will result in C++ destructors being called as a normal part of the function return.
0
0 / 0 / 1
Регистрация: 26.10.2016
Сообщений: 130
20.04.2017, 01:22  [ТС]
Max Dark, но я использовала в потоках без синхронизации и _beginthread, и WaitForSingleObject.И все работало нормально

Добавлено через 13 минут
Max Dark, Я изменила функцию. но теперь WaitForSingleObject игнорируется и программа завершается не дожидаясь завершения потоков.
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
#include <iostream>
#define _AFXDLL
#include <afxwin.h>
 
 
using namespace std;
 
int i;
CRITICAL_SECTION critsect;
 
UINT threadFunc(LPVOID pParam) {
    i++;
    Sleep(10000);
    i--;
    return 0;
}
 
UINT threadFuncWithSync(LPVOID pParam) {
    EnterCriticalSection(&critsect);
    threadFunc(NULL);
    LeaveCriticalSection(&critsect);
    return 0;
}
 
int main() {
    int n;
    cout << "Without synchronization or with ? 1/2 \n>>";
    cin >> n;
    switch (n) {
    case 1: {
        cout << "Without synchronization" << endl;
        HANDLE t1 = AfxBeginThread(threadFunc, NULL);
        HANDLE t2 = AfxBeginThread(threadFunc, NULL);
        HANDLE t3 = AfxBeginThread(threadFunc, NULL);
        HANDLE t4 = AfxBeginThread(threadFunc, NULL);
        WaitForSingleObject(t1, INFINITE);
        WaitForSingleObject(t2, INFINITE);
        WaitForSingleObject(t3, INFINITE);
        WaitForSingleObject(t4, INFINITE);
        break;
    }
    case 2: {
        cout << "With synchronization" << endl;
        InitializeCriticalSection(&critsect);
 
        HANDLE t1 = AfxBeginThread(threadFuncWithSync, NULL);
        HANDLE t2 = AfxBeginThread(threadFuncWithSync, NULL);
        HANDLE t3 = AfxBeginThread(threadFuncWithSync, NULL);
        HANDLE t4 = AfxBeginThread(threadFuncWithSync, NULL);
        WaitForSingleObject(t1, INFINITE);
        WaitForSingleObject(t2, INFINITE);
        WaitForSingleObject(t3, INFINITE);
        WaitForSingleObject(t4, INFINITE);
        break;
    }
    }
    cout << "maxI = " <<  i<< endl;
    system("pause");
    return 0;
}
0
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
12932 / 6800 / 1820
Регистрация: 18.10.2014
Сообщений: 17,211
20.04.2017, 03:20
Цитата Сообщение от wildnothing Посмотреть сообщение
я использовала в потоках без синхронизации и _beginthread, и WaitForSingleObject.И все работало нормально
Вам показалось.

Цитата Сообщение от wildnothing Посмотреть сообщение
и программа завершается не дожидаясь завершения потоков
Так а что это вообще за белиберда? Откуда вдруг взялось AfxBeginThread и с чего это вдруг вы бросились использовать эту функцию?

AfxBeginThread возвращает указатель на CWinThread. Это не HANDLE и использовать его как HANDLE нельзя. У вас все просто падает.

Не надо заниматься втыканием в код наугад бессмысленных вызовов случайных функций. Вам четко написали, что надо сделать.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
20.04.2017, 03:20
Помогаю со студенческими работами здесь

Не работает критическая секция
//--------------------------------------------------------------------------- #include &lt;vcl.h&gt; #pragma hdrstop #include...

Не работает критическая секция
Почему-то значение переменной становится равно не нулю даже при наличии критических секций. Почему? #include &lt;iostream&gt; ...

Критическая секция
Требуется применить критическую секцию для процессов через разделяемую память. Ниже привел участок кода, который это делает при условии...

Критическая секция
Очень срочно,помогите пожалуйста,на Сях,реализовать работу бензоколонки - бензин 80,92,95,98,Дизель - разлив бензина автомобилям через...

Критическая секция
такая задача. есть глобальный указатель на структуру. в main -е динамически выделяю память под массив структур. Хочу чтобы у каждой...


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

Или воспользуйтесь поиском по форуму:
15
Ответ Создать тему
Новые блоги и статьи
http://iceja.net/ сервер решения полиномов
iceja 18.01.2026
Выкатила http:/ / iceja. net/ сервер решения полиномов (находит действительные корни полиномов методом Штурма). На сайте документация по API, но скажу прямо VPS слабенький и 200 000 полиномов. . .
Первый деплой
lagorue 16.01.2026
Не спеша развернул своё 1ое приложение в kubernetes. А дальше мне интересно создать 1фронтэнд приложения и 2 бэкэнд приложения развернуть 2 деплоя в кубере получится 2 сервиса и что-бы они. . .
Расчёт переходных процессов в цепи постоянного тока
igorrr37 16.01.2026
/ * Дана цепь постоянного тока с R, L, C, k(ключ), U, E, J. Программа составляет систему уравнений по 1 и 2 законам Кирхгофа, решает её и находит: токи, напряжения и их 1 и 2 производные при t = 0;. . .
Восстановить юзерскрипты Greasemonkey из бэкапа браузера
damix 15.01.2026
Если восстановить из бэкапа профиль Firefox после переустановки винды, то список юзерскриптов в Greasemonkey будет пустым. Но восстановить их можно так. Для этого понадобится консольная утилита. . .
Изучаю kubernetes
lagorue 13.01.2026
А пригодятся-ли мне знания kubernetes в России?
Сукцессия микоризы: основная теория в виде двух уравнений.
anaschu 11.01.2026
https:/ / rutube. ru/ video/ 7a537f578d808e67a3c6fd818a44a5c4/
WordPad для Windows 11
Jel 10.01.2026
WordPad для Windows 11 — это приложение, которое восстанавливает классический текстовый редактор WordPad в операционной системе Windows 11. После того как Microsoft исключила WordPad из. . .
Classic Notepad for Windows 11
Jel 10.01.2026
Old Classic Notepad for Windows 11 Приложение для Windows 11, позволяющее пользователям вернуть классическую версию текстового редактора «Блокнот» из Windows 10. Программа предоставляет более. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru