Форум программистов, компьютерный форум, киберфорум
C/C++: WinAPI
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.79/47: Рейтинг темы: голосов - 47, средняя оценка - 4.79
 Аватар для we2seek
84 / 84 / 42
Регистрация: 25.01.2010
Сообщений: 386

Читатели - писатели

17.05.2013, 00:54. Показов 9956. Ответов 7
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Всем доброй ночи!
Готовлюсь сдавать преподавателю тему читатели-писатели, которую нам дали на самостоятельное изучение. Нужна ваша критика моего кода. Работает как-то не очень красиво, 90% работы выполняет писатель, хотя он один. Подскажите, где я затупил?
Кликните здесь для просмотра всего текста
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
#include <iostream>
#include <Windows.h>
#include <queue>
 
std::queue<int> SharedQueue;
const unsigned short QUEUE_SIZE = 15;
 
const unsigned short WRITERS_COUNT = 1;
HANDLE hWritersMutex;
HANDLE hWritersThreads[WRITERS_COUNT];
DWORD dwWritersThreadId[WRITERS_COUNT];
DWORD WINAPI WritersFunction(LPVOID lpParameter);
 
const unsigned short READERS_COUNT = 15;
HANDLE hReadersSemaphore;
HANDLE hReadersThreads[READERS_COUNT];
DWORD dwReadersThreadId[READERS_COUNT];
DWORD WINAPI ReadersFunction(LPVOID lpParameter);
 
int main() 
{
    hWritersMutex = CreateMutex( NULL, FALSE, NULL );
    
 
    for (int i = 0; i < WRITERS_COUNT; i++)
    {
        hWritersThreads[i] = CreateThread( NULL, NULL, WritersFunction, (LPVOID)i, NULL, &dwWritersThreadId[i] );
    }
 
    hReadersSemaphore = CreateSemaphore( NULL, READERS_COUNT, READERS_COUNT, NULL );
 
    for (int i = 0; i < READERS_COUNT; i++)
    {
        hReadersThreads[i] = CreateThread( NULL, NULL, ReadersFunction, (LPVOID)i, NULL, &dwReadersThreadId[i] );
    }
 
    WaitForMultipleObjects(WRITERS_COUNT, hWritersThreads, TRUE, INFINITE);
    for (int i = 0; i < WRITERS_COUNT; i++)
    {
        CloseHandle(hWritersThreads[i]);
    }
    CloseHandle(hWritersMutex);
 
    WaitForMultipleObjects(READERS_COUNT, hReadersThreads, TRUE, INFINITE);
    for (int i = 0; i < READERS_COUNT; i++)
    {
        CloseHandle(hReadersThreads[i]);
    }
    CloseHandle(hReadersSemaphore);
 
    std::cin.get();
    return 0;
}
 
DWORD WINAPI WritersFunction(LPVOID lpParam)
{
    int writerID = (int)lpParam;
    int random_number;
    DWORD dwWaitResult;
    for (int i=0; i < QUEUE_SIZE; i++)
    {
        random_number = rand()%1000;
        dwWaitResult = WaitForSingleObject(hWritersMutex, INFINITE);
        if (dwWaitResult == WAIT_OBJECT_0)
        {
            std::cout << "W " << writerID << ": " << random_number << '\n';
            SharedQueue.push(random_number);
            ReleaseMutex(hWritersMutex);
            Sleep(random_number);
        }
        else 
        {
            ReleaseMutex(hWritersMutex);
        }
    }
    return 0;
}
 
DWORD WINAPI ReadersFunction(LPVOID lpParam)
{
    int readerID = (int)lpParam;
    DWORD dwWaitResult = WaitForSingleObject(hWritersMutex, INFINITE);
    if ( dwWaitResult == WAIT_OBJECT_0 && !SharedQueue.empty() )
    {
        if ( WaitForSingleObject(hReadersSemaphore, 0L) == WAIT_OBJECT_0) 
        {
            std::cout << "R " << readerID << ": " << SharedQueue.front() << '\n';
            SharedQueue.pop();
        }
        ReleaseSemaphore( hReadersSemaphore, 1, NULL );     
    }
    ReleaseMutex(hWritersMutex);
    return 0;
}
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
17.05.2013, 00:54
Ответы с готовыми решениями:

Читатели-писатели
Здравствуйте, дорогие форумчане! Столкнулся с проблемой читателей-писателей: необходимо написать лаб.раб, демонстрирующую решение этой...

Решение задачи "писатели-читатели"
Надо написать программу на языке си под линукс, проблема писателей-читателей, все её знают(если нет лучше загуглите быстрей поймёте),...

Писатели
Каких современных птсателей можете по советовать. Детективы,фентези

7
Ушел с форума
Эксперт С++
 Аватар для Убежденный
16481 / 7444 / 1187
Регистрация: 02.05.2013
Сообщений: 11,616
Записей в блоге: 1
17.05.2013, 10:09
Проблема читателей-писателей обычно заключается в том, чтобы иметь несколько читателей,
которые не блокировали бы друг друга, и одного (или нескольких) писателей, которые могли
бы писать лишь поодиночке.

Данный код этому условию не удовлетворяет: поскольку и читатели, и писатели захватывают
hWriterMutex, в один момент времени лишь один поток может иметь доступ к очереди.
То есть, это не "single writer multiple reader", а обычная блокировка. С таким же успехом
можно было бы использовать вместо мьютекса и семафора критическую секцию, и код
получился бы проще и даже быстрее.
1
 Аватар для we2seek
84 / 84 / 42
Регистрация: 25.01.2010
Сообщений: 386
17.05.2013, 14:09  [ТС]
Убежденный, подскажите, пожалуйста, алгоритм на псевдо-языке. Я нигде не могу найти понятный мне.
0
Ушел с форума
Эксперт С++
 Аватар для Убежденный
16481 / 7444 / 1187
Регистрация: 02.05.2013
Сообщений: 11,616
Записей в блоге: 1
17.05.2013, 15:15
То, что Вам нужно, более известно под названием "Readers-Writers Locks".
Частный случай - "single writer multiple readers", иллюстрацию с примером можно
найти в книге Дж. Рихтера "Программирование для профессионалов: создание
эффективных Win32-приложений с учетом специфики 64-битной версии Windows",
глава "полезные средства синхронизации". Только ищите старое издание, в
новых изданиях эта проблема рассматривается в контексте использования
функций, появившихся в Windows Vista, а это не совсем то, что нужно.

Еще советую поискать информацию про паттерн "read copy update" (RCU), он в
различных вариациях встречается в большом количестве кода и при определенных
условиях может дать очень хорошие результаты.

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

И напоследок.
Перед тем, как звать методы класса в нескольких потоках одновременно,
полезно уточнить в документации, насколько это потокобезопасно.
STL-контейнеры из поставки Visual C++ потокобезопасны только на чтение, а
для других платформ и компиляторов все может оказаться еще хуже, и
тогда применять "readers-writers locks" вообще станет невозможно.
1
 Аватар для we2seek
84 / 84 / 42
Регистрация: 25.01.2010
Сообщений: 386
18.05.2013, 15:36  [ТС]
Немного переделал, но все равно работает так, что все время видим только писателей. Читатель берет работу только 1 раз в лучшем случае. Посоветуете что-нибудь?
Кликните здесь для просмотра всего текста
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
#include <iostream>
#include <Windows.h>
#include <tchar.h>
#include <queue>
#include <time.h>
 
std::queue<int> SharedQueue;
const unsigned short QUEUE_MAX_SIZE = 3;
 
const unsigned short WRITERS_COUNT = 2;
HANDLE hWritersMutex;
HANDLE hWritersThreads[WRITERS_COUNT];
DWORD dwWritersThreadId[WRITERS_COUNT];
DWORD WINAPI WritersFunction(LPVOID lpParameter);
 
const unsigned short READERS_COUNT = 5;
HANDLE hReadersSemaphore;
HANDLE hReadersThreads[READERS_COUNT];
DWORD dwReadersThreadId[READERS_COUNT];
DWORD WINAPI ReadersFunction(LPVOID lpParameter);
CRITICAL_SECTION cs;
 
HANDLE eCanRead = CreateEvent(NULL, TRUE, FALSE, NULL);
 
int main() 
{
    InitializeCriticalSection( &cs );
    hWritersMutex = CreateMutex( NULL, FALSE, NULL );
    hReadersSemaphore = CreateSemaphore( NULL, READERS_COUNT-1, READERS_COUNT, NULL );
 
    for (int i = 0; i < WRITERS_COUNT; i++)
    {
        hWritersThreads[i] = CreateThread( NULL, NULL, WritersFunction, (LPVOID)i, NULL, &dwWritersThreadId[i] );
    }
 
    for (int i = 0; i < READERS_COUNT; i++)
    {
        hReadersThreads[i] = CreateThread( NULL, NULL, ReadersFunction, (LPVOID)i, NULL, &dwReadersThreadId[i] );
    }
 
    WaitForMultipleObjects(WRITERS_COUNT, hWritersThreads, TRUE, INFINITE);
    for (int i = 0; i < WRITERS_COUNT; i++)
    {
        CloseHandle(hWritersThreads[i]);
    }
    CloseHandle(hWritersMutex);
 
    WaitForMultipleObjects(READERS_COUNT, hReadersThreads, TRUE, INFINITE);
    for (int i = 0; i < READERS_COUNT; i++)
    {
        CloseHandle(hReadersThreads[i]);
    }
    CloseHandle(hReadersSemaphore);
    CloseHandle(eCanRead);
 
    DeleteCriticalSection(&cs);
    std::cin.get();
    return 0;
}
 
DWORD WINAPI WritersFunction(LPVOID lpParam)
{
    srand( time(NULL) );
    int writerID = (int)lpParam;
    int random_number;
    
    while ( TRUE ) 
    //for (int i=0; i < QUEUE_MAX_SIZE*6; i++)
    {
        random_number = rand()%1000;
        
        // wait for a writers if any
        std::cout << "W " << writerID << ": writer ready...\n";
        if ( WaitForSingleObject(hWritersMutex, INFINITE) == WAIT_OBJECT_0)
        {
            // prohibit other readers begin reading
            std::cout << "W " << writerID << ": reset event...\n";
            ResetEvent(eCanRead);
 
            // waiting until other readers finished
            if ( WaitForSingleObject(hReadersSemaphore, 0L) == WAIT_OBJECT_0)
            {
                std::cout << "W " << writerID << ": " << random_number << '\n';
                SharedQueue.push(random_number);
                
                // allow reading
                SetEvent(eCanRead);
 
                // release all the readers
                ReleaseSemaphore(hReadersSemaphore, READERS_COUNT, NULL);
 
                // wait before another write thread can process
                Sleep(random_number);
 
                // release source for other writers
                ReleaseMutex(hWritersMutex);
            }
        }
    }
    
    return 0;
}
 
DWORD WINAPI ReadersFunction(LPVOID lpParam)
{
    int readerID = (int)lpParam;
    
    if ( WaitForSingleObject(eCanRead, INFINITE) == WAIT_OBJECT_0 )
    {
        if ( WaitForSingleObject(hReadersSemaphore, 0L) == WAIT_OBJECT_0 ) 
        {
            EnterCriticalSection(&cs);
            if ( !SharedQueue.empty() )
            {
                std::cout << "R " << readerID << ": " << SharedQueue.front() << '\n';
                SharedQueue.pop();
            }               
            LeaveCriticalSection(&cs);
            
            ReleaseSemaphore( hReadersSemaphore, 1, NULL );
        }
            
        Sleep(1000);
    }
    
    return 0;
}
0
Ушел с форума
Эксперт С++
 Аватар для Убежденный
16481 / 7444 / 1187
Регистрация: 02.05.2013
Сообщений: 11,616
Записей в блоге: 1
19.05.2013, 17:08
Этот код некорректен.
Ничто не мешает потоку-писателю записывать в SharedQueue одновременно с
ее чтением потоками-читателями:
C++
1
2
3
4
5
6
DWORD WINAPI WritersFunction(LPVOID lpParam)
{
    // ...
 
    // waiting until other readers finished
    if ( WaitForSingleObject(hReadersSemaphore, 0L) == WAIT_OBJECT_0)
"waiting until other readers finished" - не соответствует действительности,
ведь семафор может быть захвачен несколькими потоками.
Так что здесь писатель получает такие же права, как и писатели.
0
6 / 6 / 1
Регистрация: 14.05.2013
Сообщений: 43
23.05.2013, 11:09
Можно у вас уточнить, вы обсуждаете синхронизацию с точки зрения целостности (актуальности) данных? Влияет ли одновременное чтение файла из одного потока и запись в файл из другого потока на само создание файла? Т.е. например есть файл file.txt из которого читают и одновременно могут в него писать, может ли это привести что после записи создастся файл с другим именем file.tx, file.t0, file.0 нужно ли их синхронизировать(потоки)?
0
 Аватар для we2seek
84 / 84 / 42
Регистрация: 25.01.2010
Сообщений: 386
24.05.2013, 01:46  [ТС]
Нет, мы обсуждаем алгоритм. Для простоты в качестве общего ресурса я использую массив, т.к. контейнер STL (query) потоконебезопасен.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
24.05.2013, 01:46
Помогаю со студенческими работами здесь

Запрос читатели не бравшие книги
Есть БД библиотеки и нужно создать запрос который выведет читателей не бравших книги. Нужно зделать именно в этой базе не меняя структуру и...

Пишу бизнес-книгу, требуются первые читатели!
Мне крайне важно написать действительно полезную бизнес-книгу. (дочитайте пожалуйста объявление до конца). Что происходит после...

Отчет:Подвести итог, какой жанр предпочитают читатели каждой возрастной категории
Скажите пожалуйста как подвести итог, какой жанр предпочитают читатели каждой возрастной категории( в отчете лаба4)

Отфильтровать таблицу Выдача_книг так, чтобы остались читатели которые просрочили сдачу книг
Отфильтровать таблицу Выдача_книг так, что бы остались читатели которые просрочили сдачу книг. Добавлено через 6 минут Вот скрин...


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

Или воспользуйтесь поиском по форуму:
8
Ответ Создать тему
Новые блоги и статьи
Воспроизведение звукового файла с помощью SDL3_mixer при касании экрана Android
8Observer8 26.01.2026
Содержание блога SDL3_mixer - это библиотека я для воспроизведения аудио. В отличие от инструкции по добавлению текста код по проигрыванию звука уже содержится в шаблоне примера. Нужно только. . .
Установка Android SDK, NDK, JDK, CMake и т.д.
8Observer8 25.01.2026
Содержание блога Перейдите по ссылке: https:/ / developer. android. com/ studio и в самом низу страницы кликните по архиву "commandlinetools-win-xxxxxx_latest. zip" Извлеките архив и вы увидите. . .
Вывод текста со шрифтом TTF на Android с помощью библиотеки SDL3_ttf
8Observer8 25.01.2026
Содержание блога Если у вас не установлены Android SDK, NDK, JDK, и т. д. то сделайте это по следующей инструкции: Установка Android SDK, NDK, JDK, CMake и т. д. Сборка примера Скачайте. . .
Использование SDL3-callbacks вместо функции main() на Android, Desktop и WebAssembly
8Observer8 24.01.2026
Содержание блога Если вы откроете примеры для начинающих на официальном репозитории SDL3 в папке: examples, то вы увидите, что все примеры используют следующие четыре обязательные функции, а. . .
моя боль
iceja 24.01.2026
Выложила интерполяцию кубическими сплайнами www. iceja. net REST сервисы временно не работают, только через Web. Написала за 56 рабочих часов этот сайт с нуля. При помощи perplexity. ai PRO , при. . .
Модель сукцессии микоризы
anaschu 24.01.2026
Решили писать научную статью с неким РОманом
http://iceja.net/ математические сервисы
iceja 20.01.2026
Обновила свой сайт http:/ / iceja. net/ , приделала Fast Fourier Transform экстраполяцию сигналов. Однако предсказывает далеко не каждый сигнал (см ограничения http:/ / iceja. net/ fourier/ docs ). Также. . .
http://iceja.net/ сервер решения полиномов
iceja 18.01.2026
Выкатила http:/ / iceja. net/ сервер решения полиномов (находит действительные корни полиномов методом Штурма). На сайте документация по API, но скажу прямо VPS слабенький и 200 000 полиномов. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru