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

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

Восстановить пароль Регистрация
 
Рейтинг: Рейтинг темы: голосов - 45, средняя оценка - 4.62
VIPerZ
7 / 7 / 0
Регистрация: 26.02.2011
Сообщений: 69
16.04.2012, 11:59     Потоки. Event. Задача про обедающих философов. #1
Здравствуйте, товарищи. Возник вопрос непонимания, по которому не удалось продолбиться с помощью 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 секунд
Подскажите хотябы, как передать хоть какой-то параметр в поток! А то попытка мудрить с глобальными переменными не привела к успеху
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
16.04.2012, 11:59     Потоки. Event. Задача про обедающих философов.
Посмотрите здесь:

C++ Вопрос про потоки вывода
Задача про 2 рюкзака C++
C++ Задача про кузнечиков
Задача про температуру C++
Задача про дроби C++
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
kravam
быдлокодер
 Аватар для kravam
1512 / 872 / 44
Регистрация: 04.06.2008
Сообщений: 5,271
16.04.2012, 12:30     Потоки. Event. Задача про обедающих философов. #2
Я бы на твоём месте озаботился другим: CreateThread (); Джефри Рихтер категорически не советует создаваь потоки с помощью этой функции. Вот и не создавай. Как знать, может, твои проблемы от этого? Действуй наверняка.

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

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

Если сейчас всё получится - скину рабочий код, может кому-то ещё когда-то понадобится.
kravam
быдлокодер
 Аватар для kravam
1512 / 872 / 44
Регистрация: 04.06.2008
Сообщений: 5,271
16.04.2012, 12:45     Потоки. Event. Задача про обедающих философов. #4
Хм. Интересно, а как предполагается тестировать задачу? То есть я так предполагаю, в консоли всё это дело будет выводиться?
VIPerZ
7 / 7 / 0
Регистрация: 26.02.2011
Сообщений: 69
16.04.2012, 13:03  [ТС]     Потоки. Event. Задача про обедающих философов. #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 Посмотреть сообщение
Хм. Интересно, а как предполагается тестировать задачу? То есть я так предполагаю, в консоли всё это дело будет выводиться?
Консоль, сообщения вроде "философ хочет есть. пытается взять вилки - удача\неудача." задержка "философ думает" задержка... и так несколько циклов для каждого из философов
kravam
быдлокодер
 Аватар для kravam
1512 / 872 / 44
Регистрация: 04.06.2008
Сообщений: 5,271
16.04.2012, 13:13     Потоки. Event. Задача про обедающих философов. #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-го философа
VIPerZ
7 / 7 / 0
Регистрация: 26.02.2011
Сообщений: 69
16.04.2012, 13:15  [ТС]     Потоки. Event. Задача про обедающих философов. #7
А кроме того - всё фейлд)
По поводу номеров - они вряд ли актуальны.. это проблема настолько меня достала, что просто ужас, всё , что мне нужно - это всего-лишь передать номер в функцию потока, и передать не могу ,потому что формат не подойдет функции создания потока
kravam
быдлокодер
 Аватар для kravam
1512 / 872 / 44
Регистрация: 04.06.2008
Сообщений: 5,271
16.04.2012, 13:21     Потоки. Event. Задача про обедающих философов. #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.
Виден только один философ. А где второй-то?
VIPerZ
7 / 7 / 0
Регистрация: 26.02.2011
Сообщений: 69
16.04.2012, 15:49  [ТС]     Потоки. Event. Задача про обедающих философов. #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;
}
kravam
быдлокодер
 Аватар для kravam
1512 / 872 / 44
Регистрация: 04.06.2008
Сообщений: 5,271
16.04.2012, 21:04     Потоки. Event. Задача про обедающих философов. #10
А что такое step? Я правильно понял, что каждый философ должен поесть step раз?
VIPerZ
7 / 7 / 0
Регистрация: 26.02.2011
Сообщений: 69
16.04.2012, 22:11  [ТС]     Потоки. Event. Задача про обедающих философов. #11
просто нужно же какое-то условие для выхода из потока, ну и вот это значение - не поесть, а попытаться взять вилку и потом подумать)
kravam
быдлокодер
 Аватар для kravam
1512 / 872 / 44
Регистрация: 04.06.2008
Сообщений: 5,271
16.04.2012, 22:27     Потоки. Event. Задача про обедающих философов. #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.
Как видишь, ни одна из функций потока и не думает заканчиваться. Просто подвисла прога и всё тут.
VIPerZ
7 / 7 / 0
Регистрация: 26.02.2011
Сообщений: 69
17.04.2012, 12:16  [ТС]     Потоки. Event. Задача про обедающих философов. #13
понял, где-то таки проскакивает второй поток, где не должен бы быть.. ну тогда можно сделать как халтурное решение везде WaitForSingleObject(что-то, какое-то время а не бесконечность)
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
23.03.2014, 12:20     Потоки. Event. Задача про обедающих философов.
Еще ссылки по теме:

C++ Задача про яйца
Стандартные потоки, задача C++
C++ Ищу литературу про потоки

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

Или воспользуйтесь поиском по форуму:
qwertun
6 / 6 / 1
Регистрация: 22.12.2012
Сообщений: 446
23.03.2014, 12:20     Потоки. Event. Задача про обедающих философов. #14
Цитата Сообщение от VIPerZ Посмотреть сообщение
Окончательный, правильно работающий код, обрабатывающий философов ровно в той последовательности, как они начали хотеть есть.
Я думаю так не должно быть!
Миниатюры
Потоки. Event. Задача про обедающих философов.  
Yandex
Объявления
23.03.2014, 12:20     Потоки. Event. Задача про обедающих философов.
Ответ Создать тему
Опции темы

Текущее время: 01:27. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru