Форум программистов, компьютерный форум CyberForum.ru
Наши страницы

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
Рейтинг: Рейтинг темы: голосов - 45, средняя оценка - 4.62
VIPerZ
7 / 7 / 0
Регистрация: 26.02.2011
Сообщений: 69
#1

Потоки. Event. Задача про обедающих философов. - C++

16.04.2012, 11:59. Просмотров 5754. Ответов 13
Метки нет (Все метки)

Здравствуйте, товарищи. Возник вопрос непонимания, по которому не удалось продолбиться с помощью MSDNa и существующих тем на форуме. Что самое интересное - ощущение, что проблема именно с событиями, т.к. очень похожу задачку на потоки, только с семафорами получилось решить без каких-либо проблем. Посему прошу обьяснить в чём я тут не прав...

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

Мой код:
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
// lab1_OS2.cpp: определяет точку входа для консольного приложения.
//обедающие философы
 
#include "stdafx.h"
#include "windows.h"
#include "conio.h"
#include "stdlib.h"
 
#define min_time 300
#define max_time 1700
#define step 4
#define phil_count 10
 
HANDLE some[phil_count]; 
HANDLE Philosopher[phil_count];
 
LPTHREAD_START_ROUTINE WINAPI philosopher(LPVOID arg)
{
    int left_fork = (int)arg, right_fork = left_fork+1;
 
    for(int i = 0; i < step; i++)
    {
        Sleep(min_time + rand()%(max_time-min_time));
        printf("Philosopher[%i] want to eat.\n", left_fork);
        printf("Try to cath forks.\n");
        printf("Left[%i] and right[%i] forks - ", left_fork, right_fork);
        if (WaitForSingleObject(some[left_fork], 1) != WAIT_OBJECT_0 &
            WaitForSingleObject(some[right_fork], 1) != WAIT_OBJECT_0) 
        {
            printf("success.\n");
            SetEvent(some[left_fork]);
            SetEvent(some[right_fork]);
            printf("Eating.");
            Sleep(min_time + rand()%(max_time-min_time));
            ResetEvent(some[left_fork]);
            ResetEvent(some[right_fork]);
        }
        else printf("failed.\n");
 
        Sleep(min_time + rand()%(max_time-min_time));
        printf("Philosopher[%i] THINKING.\n", left_fork);
    }
 
    return 0;
}
 
int _tmain(int argc, _TCHAR* argv[])
{
    for (int i = 0; i < phil_count; i++)
    {
        some[i] = CreateEvent(NULL, TRUE, TRUE, NULL); //FALSE - auto-reset, TRUE - intial state is singaled
        ResetEvent(some[i]);
    }
    for (int i = 0; i < phil_count; i++)
    {
        Philosopher[i] = CreateThread(NULL, 0, philosopher((LPVOID)i), NULL, 0, NULL);
    }
    return 0;
}
С чем в данном коде проблемы: во-первых, как только происходит вызов ф-ции создания потока первый раз - тупо выполняется этот поток, а до его конца мэйн даже не пытается продолжить цикл запуска следующих потоков, а потом, когда первый поток отработал и происходит попытка создания второго потока из мэйна - вылетает эксепшн...

Добавлено через 7 часов 50 минут
Я так заметил, что на эту задачу как-будто принципиально никто не хочет отвечать, а такие темы уже были... неужели так сложно посоветовать что-то? Или хотя бы предложить другой путь реализации, где можно избежать данных проблем?

Добавлено через 38 минут
Я уже понял проблему! Если использовать тип LPTHREAD_START_ROUTINE для функции потока, то этот поток создается в единственном экземпляре и мало того, при попытке создать ещё один поток с типом LPTHREAD_START_ROUTINE вылетает эксепшн, т.к. он должен быть уникальным. Вот.

Но почему я сделал такой тип функции - для других типов программа не компилируется, когда я пытаюсь передать в ф-цию какой-то параметр, пишет, что не может конвертировать в LPTHREAD_START_ROUTINE ... а мне нужно передать параметр - номер философа из цикла...

Добавлено через 46 секунд
Подскажите хотябы, как передать хоть какой-то параметр в поток! А то попытка мудрить с глобальными переменными не привела к успеху
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
16.04.2012, 11:59
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Потоки. Event. Задача про обедающих философов. (C++):

Реальзация задачи обедающих философов с помощью событий - C++
помогите написать реальзацию задачи обедающих философов с помощью событий. не могу понять сколько событий нужно и для чего. Буду очень...

Ищу литературу про потоки - C++
Дайте, пожалуйста, нормальный ресурс где будет хорошо объяснено про потоки, мьютексы, семантика и так далее. Скачал книгу параллельное...

Вопрос про потоки вывода - C++
Здравствуйте, подскажите в чём кординальная разница между использованием cerr и cout?!?!

Не могу понять как делать задание про шифр Цезаря и потоки - C++
Слезно прошу помочь, сил больше нет... Задание: Пользователь вводит строку, зашифровать ее шифром Цезаря, рандомно найти ключ, от 0 до...

Стандартные потоки, задача - C++
Препод дал задачу из учебника. Сам толком ничего не понимаю, прошу помощи в готовом коде. Вариант 4. 1. Определить класс с именем...

Задача про монахов - C++
Условие такое: Имеется n монахов и m пирогов. Ведущий монах съедает за один раз 10 пирогов, обычный - 5, ученик монаха - 0.5. Вывести все...

13
kravam
быдлокодер
1695 / 882 / 45
Регистрация: 04.06.2008
Сообщений: 5,470
16.04.2012, 12:30 #2
Я бы на твоём месте озаботился другим: CreateThread (); Джефри Рихтер категорически не советует создаваь потоки с помощью этой функции. Вот и не создавай. Как знать, может, твои проблемы от этого? Действуй наверняка.

Добавлено через 4 минуты
CreateTbread - это Windows-функция, создающая поток. Но никогда не вы зывайте ее, если Вы пишете код на С/С++ Вместо нее Вы должны использо вать функцию beginthreadex из библиотеки Visual С++. (Если Вы работаете с другим компилятором, он должен поддерживать свой эквивалент функции CreateThread.)

Добавлено через 1 минуту
Я, решая эту задачу, пользовался библиотекой pthread; в часности, функцией pthread_create
1
VIPerZ
7 / 7 / 0
Регистрация: 26.02.2011
Сообщений: 69
16.04.2012, 12:39  [ТС] #3
Понял, но у меня уже кажется всё получилось, в задании к лабе просто сказано, что использовать для Windows системы именно эту функцию, с Unix вообще проблем не было.

Если сейчас всё получится - скину рабочий код, может кому-то ещё когда-то понадобится.
0
kravam
быдлокодер
1695 / 882 / 45
Регистрация: 04.06.2008
Сообщений: 5,470
16.04.2012, 12:45 #4
Хм. Интересно, а как предполагается тестировать задачу? То есть я так предполагаю, в консоли всё это дело будет выводиться?
0
VIPerZ
7 / 7 / 0
Регистрация: 26.02.2011
Сообщений: 69
16.04.2012, 13:03  [ТС] #5
Вобщем, вот более-менее рабочий код. Так и не понял, почему не получилось сделать кусок кода внутри одного потока, который не может быть прерван другим потоком, хотя в описании критических секций вроде бы говорилось, что она может лочится и разлочится только внутри одного потока.. а в результате выполнения четко видно, что другие потоки всё равно разлочивают её. А ещё не помог тип константы, всё равно нумерация почему-то изменяется, хотя казалось бы потоки разные, между собой не имеют ничего общего, не являются одним обьектом..

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
// lab1_OS2.cpp: определяет точку входа для консольного приложения.
//обедающие философы
 
#include "stdafx.h"
#include "windows.h"
#include "conio.h"
#include "stdlib.h"
 
#define min_time 300
#define max_time 1700
#define step 4
#define phil_count 10
 
//event for gathering into threads numbers of philophers
HANDLE iteratorControl = CreateEvent(NULL, TRUE, FALSE, NULL);//manual reset, init non-signaled
int philosopher_number = 0;
 
//event for unbreakable part of philopher activity
CRITICAL_SECTION philosopherControl;
//HANDLE philosopherControl = CreateEvent(NULL, TRUE, FALSE, NULL);//manual reset, init non-signaled
 
//events for forks and threads for filosophers
HANDLE some[phil_count]; 
HANDLE Philosophers[phil_count];
 
DWORD WINAPI philosopher(LPVOID arg)
{
    //const because somehow this value changes for all threads in random way :D
    const int left_fork = philosopher_number, right_fork = philosopher_number+1;
    ResetEvent(iteratorControl); //this event return control to other threads after getting self number
    for(int i = 0; i < step; i++)
    {
        Sleep(min_time + rand()%(max_time-min_time)); //some delay
        TryEnterCriticalSection(&philosopherControl);     //unbreakable piece of activity (start)
        printf("Philosopher[%i] want to eat.\n", left_fork);
        printf("Try to cath forks.\n");
        printf("Left[%i] and right[%i] forks - ", left_fork, right_fork);
        if ((WaitForSingleObject(some[left_fork], 1) == WAIT_OBJECT_0) &
            (WaitForSingleObject(some[right_fork], 1) == WAIT_OBJECT_0)) 
        {
            printf("success.\n");
            //occupy forks
            SetEvent(some[left_fork]);
            SetEvent(some[right_fork]);
            printf("Eating.");
            LeaveCriticalSection(&philosopherControl); //unbreakable piece of activity (stop)
            Sleep(min_time + rand()%(max_time-min_time)); //some delay
            //unoccupy forks
            ResetEvent(some[left_fork]);
            ResetEvent(some[right_fork]);
        }
        else 
        { 
            printf("failed.\n"); 
            LeaveCriticalSection(&philosopherControl); //unbreakable piece of activity (stop)
        }
 
        Sleep(min_time + rand()%(max_time-min_time)); //some delay
        printf("Philosopher[%i] THINKING.\n", left_fork);
    }
    printf("Philosopher%i exiting the program. \n", left_fork);
    return 0;
}
 
int _tmain(int argc, _TCHAR* argv[])
{
    for (int i = 0; i < phil_count; i++)
        some[i] = CreateEvent(NULL, TRUE, FALSE, NULL); //FALSE - auto-reset, TRUE - intial state is singaled
 
    for (int i = 0; i < phil_count; i++)
    {
        SetEvent(iteratorControl); //lock other threads to catch the right self number
        philosopher_number = i;
        Philosophers[i] = CreateThread(NULL, 0, philosopher, NULL, 0, NULL);
    }
 
    getch();
    return 0;
}
Добавлено через 1 минуту
Цитата Сообщение от kravam Посмотреть сообщение
Хм. Интересно, а как предполагается тестировать задачу? То есть я так предполагаю, в консоли всё это дело будет выводиться?
Консоль, сообщения вроде "философ хочет есть. пытается взять вилки - удача\неудача." задержка "философ думает" задержка... и так несколько циклов для каждого из философов
0
kravam
быдлокодер
1695 / 882 / 45
Регистрация: 04.06.2008
Сообщений: 5,470
16.04.2012, 13:13 #6
ОК, попробуем потестить
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
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
++++++++++++++++++
Philosopher[2] want to eat.
Try to cath forks.
Left[2] and right[3] forks - Philosopher[3] want to eat.
Philosopher[3] want to eat.
Philosopher[4] want to eat.
Try to cath forks.
Left[4] and right[5] forks - Try to cath forks.
Try to cath forks.
Left[3] and right[4] forks - Philosopher[5] want to eat.
Philosopher[7] want to eat.
Philosopher[6] want to eat.
Try to cath forks.
Left[6] and right[7] forks - Try to cath forks.
Left[5] and right[6] forks - Left[3] and right[4] forks - Philosopher[9] want to
 eat.
Philosopher[8] want to eat.
Try to cath forks.
Try to cath forks.
Left[9] and right[10] forks - failed.
Philosopher[9] want to eat.
Try to cath forks.
Left[9] and right[10] forks - Try to cath forks.
Left[8] and right[9] forks - Left[7] and right[8] forks - failed.
failed.
failed.
failed.
failed.
failed.
failed.
failed.
failed.
Philosopher[2] THINKING.
Philosopher[9] THINKING.
Philosopher[3] THINKING.
Philosopher[4] THINKING.
Philosopher[5] THINKING.
Philosopher[9] THINKING.
Philosopher[3] THINKING.
Philosopher[6] THINKING.
Philosopher[7] THINKING.
Philosopher[8] THINKING.
Philosopher[2] want to eat.
Try to cath forks.
Left[2] and right[3] forks - Philosopher[4] want to eat.
Philosopher[9] want to eat.
Philosopher[3] want to eat.
Try to cath forks.
Try to cath forks.
Try to cath forks.
Left[4] and right[5] forks - Left[9] and right[10] forks - Left[3] and right[4]
forks - Philosopher[5] want to eat.
Philosopher[9] want to eat.
Try to cath forks.
Try to cath forks.
Left[5] and right[6] forks - Left[9] and right[10] forks - failed.
Philosopher[3] want to eat.
Try to cath forks.
Left[3] and right[4] forks - failed.
Philosopher[6] want to eat.
Philosopher[8] want to eat.
Philosopher[7] want to eat.
failed.
Try to cath forks.
Try to cath forks.
Try to cath forks.
Left[6] and right[7] forks - Left[8] and right[9] forks - Left[7] and right[8] f
orks - failed.
failed.
failed.
failed.
failed.
failed.
failed.
Philosopher[9] THINKING.
Philosopher[9] THINKING.
Philosopher[2] THINKING.
Philosopher[4] THINKING.
Philosopher[3] THINKING.
Philosopher[5] THINKING.
Philosopher[3] THINKING.
Philosopher[7] THINKING.
Philosopher[6] THINKING.
Philosopher[8] THINKING.
Philosopher[9] want to eat.
Try to cath forks.
Left[9] and right[10] forks - Philosopher[2] want to eat.
Philosopher[9] want to eat.
Try to cath forks.
Try to cath forks.
Left[2] and right[3] forks - Left[9] and right[10] forks - Philosopher[4] want t
o eat.
Try to cath forks.
Left[4] and right[5] forks - Philosopher[3] want to eat.
failed.
Try to cath forks.
Left[3] and right[4] forks - Philosopher[5] want to eat.
failed.
Try to cath forks.
Left[5] and right[6] forks - Philosopher[3] want to eat.
Try to cath forks.
Left[3] and right[4] forks - Philosopher[7] want to eat.
failed.
Philosopher[6] want to eat.
Philosopher[8] want to eat.
Try to cath forks.
Try to cath forks.
Try to cath forks.
Left[7] and right[8] forks - Left[6] and right[7] forks - Left[8] and right[9] f
orks - failed.
failed.
failed.
failed.
failed.
failed.
failed.
Philosopher[9] THINKING.
Philosopher[9] THINKING.
Philosopher[2] THINKING.
Philosopher[3] THINKING.
Philosopher[4] THINKING.
Philosopher[5] THINKING.
Philosopher[3] THINKING.
Philosopher[6] THINKING.
Philosopher[7] THINKING.
Philosopher[8] THINKING.
Philosopher[9] want to eat.
Try to cath forks.
Left[9] and right[10] forks - Philosopher[9] want to eat.
Try to cath forks.
Left[9] and right[10] forks - failed.
Philosopher[2] want to eat.
failed.
Try to cath forks.
Left[2] and right[3] forks - Philosopher[4] want to eat.
Philosopher[3] want to eat.
Try to cath forks.
Try to cath forks.
Left[4] and right[5] forks - Left[3] and right[4] forks - Philosopher[5] want to
 eat.
Try to cath forks.
Left[5] and right[6] forks - Philosopher[3] want to eat.
Try to cath forks.
Left[3] and right[4] forks - failed.
Philosopher[7] want to eat.
Philosopher[8] want to eat.
Philosopher[6] want to eat.
Try to cath forks.
Try to cath forks.
Try to cath forks.
Left[7] and right[8] forks - Left[8] and right[9] forks - Left[6] and right[7] f
orks - failed.
failed.
failed.
failed.
failed.
failed.
failed.
Philosopher[9] THINKING.
Philosopher9 exiting the program.
Philosopher[9] THINKING.
Philosopher9 exiting the program.
Philosopher[2] THINKING.
Philosopher2 exiting the program.
Philosopher[3] THINKING.
Philosopher[4] THINKING.
Philosopher3 exiting the program.
Philosopher4 exiting the program.
Philosopher[5] THINKING.
Philosopher5 exiting the program.
Philosopher[3] THINKING.
Philosopher3 exiting the program.
Philosopher[6] THINKING.
Philosopher[7] THINKING.
Philosopher[8] THINKING.
Philosopher6 exiting the program.
Philosopher7 exiting the program.
Philosopher8 exiting the program.
Меня смущает одна вещь; насколько я понял философов 10, но что-то я не наблюдаю действия 0-го философа
0
VIPerZ
7 / 7 / 0
Регистрация: 26.02.2011
Сообщений: 69
16.04.2012, 13:15  [ТС] #7
А кроме того - всё фейлд)
По поводу номеров - они вряд ли актуальны.. это проблема настолько меня достала, что просто ужас, всё , что мне нужно - это всего-лишь передать номер в функцию потока, и передать не могу ,потому что формат не подойдет функции создания потока
0
kravam
быдлокодер
1695 / 882 / 45
Регистрация: 04.06.2008
Сообщений: 5,470
16.04.2012, 13:21 #8
Ну для того чтобы научиться передавать аргумент в функцию потока, необязательно решать задачу о философах. Актуальны номера или нет- решать тебе. Вот отчёт работы твоей программы с двумя философами:
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
Philosopher[1] want to eat.
Philosopher[1] want to eat.
Try to cath forks.
Try to cath forks.
Left[1] and right[2] forks - Left[1] and right[2] forks - failed.
failed.
Philosopher[1] THINKING.
Philosopher[1] THINKING.
Philosopher[1] want to eat.
Philosopher[1] want to eat.
Try to cath forks.
Try to cath forks.
Left[1] and right[2] forks - Left[1] and right[2] forks - failed.
failed.
Philosopher[1] THINKING.
Philosopher[1] THINKING.
Philosopher[1] want to eat.
Philosopher[1] want to eat.
Try to cath forks.
Try to cath forks.
Left[1] and right[2] forks - Left[1] and right[2] forks - failed.
failed.
Philosopher[1] THINKING.
Philosopher[1] THINKING.
Philosopher[1] want to eat.
Philosopher[1] want to eat.
Try to cath forks.
Try to cath forks.
Left[1] and right[2] forks - Left[1] and right[2] forks - failed.
failed.
Philosopher[1] THINKING.
Philosopher[1] THINKING.
Philosopher1 exiting the program.
Philosopher1 exiting the program.
Виден только один философ. А где второй-то?
0
VIPerZ
7 / 7 / 0
Регистрация: 26.02.2011
Сообщений: 69
16.04.2012, 15:49  [ТС] #9
Немного пофиксил проблему номеров, теперь с ними всё работает абсолютно четко, я разобрался с тем как работают события с помощью экспериментов, но теперь возник ещё один вопрос - иногда соседний философ тоже хватает вилки, хотя они уже заняты другим потоком и события на них стоят!

Почти-почти рабочий код:
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
// lab1_OS2.cpp: определяет точку входа для консольного приложения.
//обедающие философы
 
#include "stdafx.h"
#include "windows.h"
#include "conio.h"
#include "stdlib.h"
 
#define min_time 300
#define max_time 1700
#define step 4
#define phil_count 10
 
//event for gathering into threads numbers of philophers
HANDLE iteratorControl = CreateEvent(NULL, TRUE, TRUE, NULL);//manual reset, init non-signaled
int philosopher_number = 0;
 
//event for unbreakable part of philopher activity
//CRITICAL_SECTION philosopherControl;
//HANDLE philosopherControl2 = CreateEvent(NULL, TRUE, TRUE, NULL);//manual reset, init non-signaled
 
//events for forks and threads for filosophers
HANDLE some[phil_count]; 
HANDLE Philosophers[phil_count];
 
DWORD WINAPI philosopher(LPVOID arg)
{
    //const because somehow this value changes for all threads in random way :D
    const int left_fork = philosopher_number, right_fork = philosopher_number+1;
    SetEvent(iteratorControl); //this event return control to other threads after getting self number
    for(int i = 0; i < step; i++)
    {
        Sleep(min_time + rand()%(max_time-min_time)); //some delay
        //TryEnterCriticalSection(&philosopherControl);     //unbreakable piece of activity (start)
        //WaitForSingleObject(philosopherControl2, INFINITE);
        //ResetEvent(philosopherControl2);
        printf("Philosopher[%i] want to eat.\n", left_fork);
        if (WaitForSingleObject(some[left_fork], 1) == WAIT_TIMEOUT)     
        {
            if (WaitForSingleObject(some[right_fork], 1) == WAIT_TIMEOUT)
            {
                printf("L[%i] n r[%i] forks - success.\n", left_fork, right_fork);
                //occupy forks
                SetEvent(some[left_fork]);
                SetEvent(some[right_fork]);
                printf("begin Eating[%i].\n", left_fork);
                //LeaveCriticalSection(&philosopherControl); //unbreakable piece of activity (stop)
                //SetEvent(philosopherControl2);
                Sleep(min_time + rand()%(max_time-min_time)); //some delay
                printf("end   Eating[%i].\n", left_fork);
                //unoccupy forks
                ResetEvent(some[left_fork]);
                ResetEvent(some[right_fork]);
            }
        }
        else if ((WaitForSingleObject(some[left_fork], 1) == WAIT_OBJECT_0) ||
            (WaitForSingleObject(some[right_fork], 1) == WAIT_OBJECT_0))
        { 
            printf("L[%i] n r[%i] forks - failed.\n", left_fork, right_fork); 
            //LeaveCriticalSection(&philosopherControl); //unbreakable piece of activity (stop)
            //SetEvent(philosopherControl2);
        }
 
        Sleep(min_time + rand()%(max_time-min_time)); //some delay
        printf("Philosopher[%i] thinking.\n", left_fork);
    }
    printf("Philosopher%i EXITING the program. \n", left_fork);
    return 0;
}
 
int _tmain(int argc, _TCHAR* argv[])
{
    for (int i = 0; i < phil_count; i++)
        some[i] = CreateEvent(NULL, TRUE, FALSE, NULL); //FALSE - auto-reset, TRUE - intial state is singaled
 
    for (int i = 0; i < phil_count; i++)
    {
        WaitForSingleObject(iteratorControl, INFINITE);
        ResetEvent(iteratorControl); //lock other threads to catch the right self number
        philosopher_number = i;
        Philosophers[i] = CreateThread(NULL, 0, philosopher, NULL, 0, NULL);
    }
 
    /*int test1, test2, test3, test4, test5, test6;
    test1 = WAIT_OBJECT_0;
    test2 = WAIT_ABANDONED;
    test3 = WAIT_TIMEOUT;
    test4 = WAIT_FAILED;
 
    test5 = WaitForSingleObject(some[0], 1);
    SetEvent(some[0]);
    test5 = WaitForSingleObject(some[0], 1);
    ResetEvent(some[0]);
    test5 = WaitForSingleObject(some[0], 1);
    
    test6 = WaitForSingleObject(some[1], 1);
    SetEvent(some[1]);
    test6 = WaitForSingleObject(some[1], 1);
    ResetEvent(some[1]);
    test6 = WaitForSingleObject(some[1], 1);*/
 
    getch();
    return 0;
}
Добавлено через 5 минут
Всё было бы правильно, если бы в выводе после begin eat[number] , если появляется попытка захватить вилки, где есть вилка с этим же номером - то должно быть фейлд, и саксес только после end eating[number] , а там почему-то частенько проскакивает саксес

Добавлено через 1 час 55 минут
Окончательный, правильно работающий код, обрабатывающий философов ровно в той последовательности, как они начали хотеть есть.
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
// lab1_OS2.cpp: определяет точку входа для консольного приложения.
//обедающие философы
 
#include "stdafx.h"
#include "windows.h"
#include "conio.h"
#include "stdlib.h"
#include "list"
 
#define min_time 300
#define max_time 1700
#define step 2
#define phil_count 5
 
using namespace std;
 
list<int> Threads_sequence;
 
//event for gathering into threads numbers of philophers
HANDLE iteratorControl = CreateEvent(NULL, TRUE, TRUE, NULL);//manual reset, init signaled
int philosopher_number = 0;
 
//cs for unbreakable part of philosopher activity
CRITICAL_SECTION philosopherControl; 
 
//events for forks and threads for philosophers
HANDLE some[phil_count]; 
HANDLE Philosophers[phil_count];
 
DWORD WINAPI philosopher(LPVOID arg)
{
    //const because somehow this value changes for all threads in random way :D
    const int left_fork = philosopher_number, right_fork = philosopher_number+1;
    SetEvent(iteratorControl); //this event return control to other threads after getting self number
    for(int i = 0; i < step; i++)
    {
        Sleep(min_time + rand()%(max_time-min_time)); //some delay
        Threads_sequence.push_back(left_fork);
                            //cycle for right sequence of threads critical section entering
                            while(true)
                            {
                                if (Threads_sequence.front() == left_fork) { Threads_sequence.pop_back(); break; }
                                else continue;
                            }
        EnterCriticalSection(&philosopherControl);     //unbreakable piece of activity (start)
        if (WaitForSingleObject(some[left_fork], 1) == WAIT_TIMEOUT)     
        {
            if (WaitForSingleObject(some[right_fork], 1) == WAIT_TIMEOUT)
            {
                printf("Philosopher[%i] want to eat. L[%i] n r[%i] forks - success.\n", left_fork, left_fork, right_fork);
                //occupy forks
                SetEvent(some[left_fork]);
                SetEvent(some[right_fork]);
                LeaveCriticalSection(&philosopherControl); //unbreakable piece of activity (stop)
                printf("begin Eating[%i].\n", left_fork);
                Sleep(min_time + rand()%(max_time-min_time)); //some delay
                //unoccupy forks
                ResetEvent(some[left_fork]);
                ResetEvent(some[right_fork]);
                printf("end   Eating[%i].\n", left_fork);
            }
            else if (WaitForSingleObject(some[right_fork], 1) == WAIT_OBJECT_0)
            {
                printf("Philosopher[%i] want to eat. R[%i] fork - failed.\n", left_fork, right_fork);
            }
        }
        else if (WaitForSingleObject(some[left_fork], 1) == WAIT_OBJECT_0)
        {
            printf("Philosopher[%i] want to eat. L[%i] fork - failed.\n", left_fork, left_fork);
        }
        else if (WaitForSingleObject(some[right_fork], 1) == WAIT_OBJECT_0)
        {
            printf("Philosopher[%i] want to eat. R[%i] fork - failed.\n", left_fork, right_fork);
        }
        else if ((WaitForSingleObject(some[right_fork], 1) == WAIT_OBJECT_0) & (WaitForSingleObject(some[left_fork], 1) == WAIT_OBJECT_0))
        {
            printf("Philosopher[%i] want to eat. L[%i] n r[%i] forks - failed.\n", left_fork, left_fork, right_fork);
        }
        else 
        {
            printf("Philosopher[%i] want to eat. Error on [%i].\n", left_fork, left_fork);
        }
        LeaveCriticalSection(&philosopherControl); //unbreakable piece of activity (stop)
        Sleep(min_time + rand()%(max_time-min_time)); //some delay
        printf("Philosopher[%i] thinking.\n", left_fork);
    }
    printf("Philosopher%i EXITING the program. \n", left_fork);
    return 0;
}
 
int _tmain(int argc, _TCHAR* argv[])
{
    InitializeCriticalSection(&philosopherControl);
 
    for (int i = 0; i < phil_count; i++)
    {
        some[i] = CreateEvent(NULL, TRUE, FALSE, NULL); //FALSE - auto-reset, TRUE - intial state is singaled
        ResetEvent(some[i]);
    }
 
    for (int i = 0; i < phil_count; i++)
    {
        WaitForSingleObject(iteratorControl, INFINITE);
        ResetEvent(iteratorControl); //lock other threads to catch the right self number
        philosopher_number = i;
        Philosophers[i] = CreateThread(NULL, 0, philosopher, NULL, 0, NULL);
    }
 
    //int test1, test2, test3, test4, test5, test6;
    //test1 = WAIT_OBJECT_0;
    //test2 = WAIT_ABANDONED;
    //test3 = WAIT_TIMEOUT;
    //test4 = WAIT_FAILED;
 
    //SetEvent(some[0]);
    //test5 = WaitForSingleObject(some[0], 1);//after set = 0 = WAIT_OBJECT_0
    //WaitForSingleObject(some[0], INFINITE);//going through wait
    //test5 = WaitForSingleObject(some[0], 1);
 
    //ResetEvent(some[0]);
    //test5 = WaitForSingleObject(some[0], 1);//after reset = 258 = WAIT_TIMEOUT
    //WaitForSingleObject(some[0], 5000);//stuck on wait if infinite
    //test5 = WaitForSingleObject(some[0], 1);
 
    getch();
    return 0;
}
1
kravam
быдлокодер
1695 / 882 / 45
Регистрация: 04.06.2008
Сообщений: 5,470
16.04.2012, 21:04 #10
А что такое step? Я правильно понял, что каждый философ должен поесть step раз?
0
VIPerZ
7 / 7 / 0
Регистрация: 26.02.2011
Сообщений: 69
16.04.2012, 22:11  [ТС] #11
просто нужно же какое-то условие для выхода из потока, ну и вот это значение - не поесть, а попытаться взять вилку и потом подумать)
0
kravam
быдлокодер
1695 / 882 / 45
Регистрация: 04.06.2008
Сообщений: 5,470
16.04.2012, 22:27 #12
Ну вообще для демонстрации программы шаг необязательно и даже плохо делать равным двум. Это многопоточность. Потому что можно увидеть если каждый философ ровно два раза что-то там сделает? Ничего
НАпиши вот так:
C++
1
for(int i = 0; i < 1; )
И очень скоро твоя программа подвиснет. Для чистоты эксперимента можешь сделать шаг равным какому-то реальному числу. В общем, программа зависла у меня при step== 5

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
Philosopher[0] want to eat. L[0] n r[1] forks - success.
begin Eating[0].
Philosopher[2] want to eat. L[2] n r[3] forks - success.
begin Eating[2].
Philosopher[1] want to eat. L[1] fork - failed.
Philosopher[4] want to eat. L[4] n r[5] forks - success.
begin Eating[4].
Philosopher[3] want to eat. L[3] fork - failed.
end   Eating[0].
end   Eating[2].
Philosopher[1] thinking.
Philosopher[3] thinking.
end   Eating[4].
Philosopher[0] thinking.
Philosopher[2] thinking.
Philosopher[4] thinking.
Philosopher[2] want to eat. L[2] n r[3] forks - success.
begin Eating[2].
Philosopher[1] want to eat. R[2] fork - failed.
end   Eating[2].
Philosopher[1] thinking.
Philosopher[2] thinking.
Philosopher[1] want to eat. L[1] n r[2] forks - success.
begin Eating[1].
end   Eating[1].
Philosopher[1] thinking.
Как видишь, ни одна из функций потока и не думает заканчиваться. Просто подвисла прога и всё тут.
0
VIPerZ
7 / 7 / 0
Регистрация: 26.02.2011
Сообщений: 69
17.04.2012, 12:16  [ТС] #13
понял, где-то таки проскакивает второй поток, где не должен бы быть.. ну тогда можно сделать как халтурное решение везде WaitForSingleObject(что-то, какое-то время а не бесконечность)
0
qwertun
6 / 6 / 1
Регистрация: 22.12.2012
Сообщений: 464
23.03.2014, 12:20 #14
Цитата Сообщение от VIPerZ Посмотреть сообщение
Окончательный, правильно работающий код, обрабатывающий философов ровно в той последовательности, как они начали хотеть есть.
Я думаю так не должно быть!
0
Миниатюры
Потоки. Event. Задача про обедающих философов.  
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
23.03.2014, 12:20
Привет! Вот еще темы с ответами:

Задача про графы - C++
помогите если не сложно Тексты нужно переписывать в тело сообщения!

задача про графы - C++
Написать программу отыскания кратчайших путей между всеми парами вершин ориентированного графа по его списковому представлению

Задача про зайца - C++
В небольшой посадке живет заяц. Выскочив из норы и бегая по снегу, он оставил следы. Определить где находится заяц. ВХОДНЫЕ ДАНЫЕ Карта...

Задача про числа - C++
Думаю, думаю, но всё равно не могу понять как решить. Задача: Дан массив из положительных чисел и два числа a и b. Мы можем отнять...


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

Или воспользуйтесь поиском по форуму:
14
Yandex
Объявления
23.03.2014, 12:20
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru