Форум программистов, компьютерный форум, киберфорум
C/С++ под Linux
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.55/11: Рейтинг темы: голосов - 11, средняя оценка - 4.55
0 / 0 / 0
Регистрация: 10.10.2016
Сообщений: 34
1

Mutex. Синхронизация потоков. Pthread_cond_wait

29.12.2019, 12:04. Показов 2303. Ответов 8

Author24 — интернет-сервис помощи студентам
Здравствуйте! Столкнулась с проблемой в написании лабораторной работы. Задание звучит так:
Напишите функцию, удовлетворяющую следующим условиям:
a. Прототип функции: int lab_pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, unsigned int timetowait);
b. Входные параметры: адрес условной переменной, адрес мьютекса, количество миллисекунд, устанавливаемое для ожидания условной переменной.
c. Функция возвращает следующие значения:
- 0 в случае успешного выполнения функции,
- 1 в случае, если время ожидания условной переменной превысило заданное в параметре timetowait количество миллисекунд,
-1в случае любой ошибки.
При реализации функции разрешается использовать стандартные структуры и функции библиотек ОС Linux, за исключением функции pthread_cond_timedwait(…).

Ниже представлена реализация этого задания
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
#include <stdio.h>
#include <stdlib.h> 
#include <unistd.h>
#include <sys/stat.h>
#include <string.h> 
#include <time.h> 
#include <sys/errno.h>
#include <unistd.h> // for usleep
#include <pthread.h>
 
struct param
{
pthread_cond_t *cond;
int timewait;
};
pthread_mutex_t my_sync;
pthread_t kidA,kidB;
pthread_cond_t rx;
    int anykey=0;
    int retval=22;
    int flag;
    int t;
 
void *func(void *str)
{
struct param *qw=(struct param *)str;
struct param wq=*qw;
sleep (wq.timewait);
flag=1;
pthread_cond_signal(wq.cond);
}
 
 
int lab_pthread_cond_timedwait(pthread_cond_t *cond,pthread_mutex_t *mutex, unsigned int timetowait)
{
flag=0;
struct param conds;
pthread_t tid;
conds.timewait=timetowait;
conds.cond=cond;
pthread_create(&tid,NULL,&func,&conds);
pthread_cond_wait(cond,mutex);
if (flag==0)
 {
 return 0;
 }
else if (flag==1)
 {
 return 1;
 }
else
 {
 return -1;
 }
}
 
 
void * streamA () //Поток А
{
srand(time(NULL));
    for (;;)
    {
        sleep(2.5);
    printf("----------\n");
        pthread_mutex_lock (&my_sync);
        printf("Thread A locks MUTEX\n");
    retval=0;
    int sl;
    sl=rand()%3;
        sleep (sl);
    pthread_cond_signal(&rx);
        printf("Thread A keeps locking MUTEX\n");
        pthread_mutex_unlock (&my_sync);
    printf("Thread A unlocks MUTEX\n*******\n");
    }
}
 
void * streamB () // Поток B
{
    for (;;)
    {
    int res;
        sleep(1.5);
        pthread_mutex_lock(&my_sync);
    printf("Thread B locks MUTEX\n");
    while (retval!=0)
    res=lab_pthread_cond_timedwait(&rx,&my_sync,t);
    if (res==0)
    printf("Success. Return:%d\n",res);
    else if (res==1)
    printf("ETIMEDOUT. Return:%d\n",res);
    else
    perror("cond_error:\n");
    printf("Thread B ends.\n");
    retval=1;
    pthread_mutex_unlock(&my_sync);
    }
}
 
int main(int argc,char **argv)
{
    t=atoi(argv[1]);
    t=t/1000;   
    pthread_attr_t attr;
    pthread_mutex_init (&my_sync, NULL);
    pthread_attr_init(&attr);
    pthread_create (&kidA, &attr, streamA, NULL);;
    pthread_create (&kidB, &attr, streamB, NULL);
    pthread_join(kidA,NULL);
    pthread_join(kidB,NULL);
}
Проблема заключается в том, что внутри собственной функции я вызываю Pthread_cond_wait, что не удовлетворяет условию при написании работы. Подскажите, пожалуйста, как можно заменить эту функцию и на что?
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
29.12.2019, 12:04
Ответы с готовыми решениями:

Синхронизация потоков без использования mutex
Была написана прога (в целях лабораторной работы) синхронизации потоков,на защиту дали переделать...

Почему pthread_cond_wait() функция получает в аргументе mutex, и что делает с ним?
почему pthread_cond_wait() функция получает в аргументе mutex, и что делает с ним?

Синхронизация потоков в OC Linux
Здравствуйте. Помогите, пожалуйста, решить проблему. Решите классическую проблему «поставщик –...

Синхронизация потоков - найти ошибку в коде
не получается разрулить следующую ситуацию. дано: переменная. 2 треда. 1 поток рулит...

8
724 / 224 / 72
Регистрация: 01.03.2011
Сообщений: 629
30.12.2019, 08:30 2
Цитата Сообщение от MollyLu Посмотреть сообщение
Проблема заключается в том, что внутри собственной функции я вызываю Pthread_cond_wait, что не удовлетворяет условию при написании работы
В описании задания вы говорите о запрете только на pthread_cond_timedwait() т.е. все хорошо.
Запрет на использование pthread_cond_wait() автоматом запрещает все pthread_cond_xxx т.к если вы организуете очередь ожидания руками (вариант залезть в потроха libc не рассматриваем как грязный), то нить вставшую в ожидание на условной переменной будет не разбудить через стандартную pthread_cond_signal().
Код течет, нужно убивать нить с таймером если нас разбудили не по таймеру
0
0 / 0 / 0
Регистрация: 10.10.2016
Сообщений: 34
30.12.2019, 14:27  [ТС] 3
prik, как мне объяснили по заданию, то что _timedwait, что _wait в данной работе запрещены (так как очень похожи) и нужно прям самим написать аналог-прототип. Только вот как это сделать без _wait большая проблема для меня. Я залезла в библиотеку, где хранится данная функция, но это тоже особо ничего не дало(

Вот ссылка на библиотеку https://github.com/lattera/gli... ond_wait.c
0
724 / 224 / 72
Регистрация: 01.03.2011
Сообщений: 629
30.12.2019, 22:24 4
MollyLu, не готов ответить однозначно
я бы пробовал так:
пишем замены для всех pthrend_cond_xxx
1й вызов pthred_cond_init создает "мастер" нить которая будет отвечать за таймер и посылку сигналов спящим нитям
lab_pthread_cond_t представляет собой одну переменную атомарного типа, очередь из структур {pthread_t tid; int timeout;} отсортированную по таймауту и наверное мьютекс для защиты всей этой структуры.
pthread_cond_timedwait() - добавить элемент в очередь, просигналить "мастеру", разлочить мьютекс, ждать сигнала.
pthread_cond_signal() - просигналить "мастеру" - буди нить из головы очереди.
0
724 / 224 / 72
Регистрация: 01.03.2011
Сообщений: 629
03.01.2020, 16:55 5
UP: Проспавшись и слегка отошедши, перечитал...
Дополнительные нити не нужны, берем такую структуру:
C
1
2
3
4
5
struct mypthread_cond {
        pthread_mutex_t mutex;
        pthread_t       waiters[MPC_NWAITERS]; /* Лучше массив заменить на очередь, но для теста пойдет. */
};
typedef struct  mypthread_cond          *mypthread_cond_t;
И делаем ожидание на ppoll():
Кликните здесь для просмотра всего текста
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
int mpc_timedwait(mypthread_cond_t cond, pthread_mutex_t *mutexp,                                                                                             
    const struct timespec *abs)                                                                                                                               
{                                                                                                                                                             
        sigset_t mask;                                                                                                                                        
        size_t i;                                                                                                                                             
        int error;                                                                                                                                            
                                                                                                                                                                                                                                                                                                                          
        error = EBUSY;                                                                                                                                        
        pthread_mutex_lock(&cond->mutex);                                                                                                                     
        for (i = 0; i < MPC_NWAITERS; i++) {                                                                                                                  
                if (cond->waiters[i] == NULL) {                                                                                                               
                        cond->waiters[i] = pthread_self();                                                                                                    
                        error = 0;                                                                                                                            
                        break;                                                                                                                                
                }                                                                                                                                             
        }                                                                                                                                                     
        pthread_mutex_unlock(&cond->mutex);                                                                                                                   
        if (error)                                                                                                                                            
                return (error);                                                                                                                               
                                                                                                                                                              
        pthread_sigmask(0, NULL, &mask);                                                                                                                      
        sigdelset(&mask, MPC_SIGNO);                                                                                                                          
        if ((error = pthread_mutex_unlock(mutexp)))                                                                                                           
                return (error);                                                                                                                               
        error = ppoll(NULL, 0, abs, &mask);                                                                                                                   
        /* XXX */                                                                                                                                             
        if (pthread_mutex_lock(mutexp)) {
#define XXXMSG "mpc_timedwait: can't re-acquire the mutex\n"
                write(2, XXXMSG, sizeof(XXXMSG) - 1);
#undef XXXMSG
                _exit(1);
        }
 
        if (error == -1 && errno == EINTR)
                return (0);
 
        if (error == 0)
                return (ETIMEDOUT);
        return (error);
}
 
int mypthread_cond_wait(mypthread_cond_t *condp,                                                                                                              
                        pthread_mutex_t *mutexp)                                                                                                              
{                                                                                                                                                             
        mypthread_cond_t cond;                                                                                                                                
                                                                                                                                                              
        if (condp == NULL)                                                                                                                                    
                return (EFAULT);                                                                                                                              
        cond = *condp;                                                                                                                                        
                                                                                                                                                                                                                                                                               
        return (mpc_timedwait(cond, mutexp, NULL));                                                                                                           
}

Остальные pthread_cond_* не показываю, надеюсь, идея понятна. Вроде работает, покрайней мере проходит простейшие тесты.
С наступившим и удачи!
0
0 / 0 / 0
Регистрация: 10.10.2016
Сообщений: 34
07.01.2020, 12:24  [ТС] 6
prik, и вас с наступившим! Извините, долго разбиралась еще сама особенно с тем, как написать для остальных команд такой же шаблон, по вашему примеру, все же не до конца понимаю, как это сделать. И есть ли еще альтернативные варианты?
0
724 / 224 / 72
Регистрация: 01.03.2011
Сообщений: 629
07.01.2020, 12:44 7
Цитата Сообщение от MollyLu Посмотреть сообщение
все же не до конца понимаю, как это сделать
cond_init() должен выделить память под структуру и инициализировать ее, destroy() - убедиться, что очередь спящих нитей пуста и освободить все что выделил init. signal - убедиться, что очередь не пуста и разбудить хотя бы одну ждущую нить. Остальное - обвязки над ними по аналогии, например brodcast() - вызвать signal() для всех нитей из списка ожидания.
Цитата Сообщение от MollyLu Посмотреть сообщение
И есть ли еще альтернативные варианты?
Годиться любой объект на котором можно синхронизироваться, например футекс или пайп.
0
0 / 0 / 0
Регистрация: 10.10.2016
Сообщений: 34
07.01.2020, 17:07  [ТС] 8
я имею в виду есть ли дркгие варианты написании аналогичной функции, без изменения других pthread_cond_*? Просто это по факту похоже на переписывание библиотеки, просто со своими названием всех других функций. Я думаю, должен быть какой-то более простой вариант, не такой ресурсозатратный
0
724 / 224 / 72
Регистрация: 01.03.2011
Сообщений: 629
08.01.2020, 08:58 9
Цитата Сообщение от MollyLu Посмотреть сообщение
Просто это по факту похоже на переписывание библиотеки, просто со своими названием всех других функций
Так от вас фактически этого и хотят.
Что бы ограничится заменой только одной функции нужно взять определение структуры на которою ссылается pthread_cond_t из libc (причем от версии libc из системы на которой вы будете сдавать это задание), утянуть в свой проект с десяток вспомогательных ф-ций не экспортируемых из libc, и наконец, переписать своими словами pthread_cond_timedwait(). Но будет ли это проще?
0
08.01.2020, 08:58
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
08.01.2020, 08:58
Помогаю со студенческими работами здесь

Синхронизация потоков для вычисления дисперсии
Доброго времени суток. Необходима помощь с решением задачи. Задача состоит в следующем: 1. Есть...

Синхронизация потоков, thread-safe usleep
Постановка задачи: Создать 2N+1 потоков. N потоков пишут в общий буфер (далее ОБ), N + 1 потоков...

Mutex и синхронизация потоков
Задача, как сказал руководитель, на три строчки, но не имею ни малейшего понятия как ее решать. ...

Mutex - синхронизация
У меня возник вопрос по мьютексам и их синхронизации, видимо, я не понимаю до конца механизм их...


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

Или воспользуйтесь поиском по форуму:
9
Ответ Создать тему
Новые блоги и статьи
Как обучить нейросеть создания картинок на Python
bytestream 24.01.2025
В эпоху цифровых технологий искусственный интеллект становится неотъемлемой частью творческого процесса. Особое место в этой области занимает разработка и обучение нейронных сетей для создания. . .
Как обучить нейросеть генерации текста на Python
bytestream 24.01.2025
В современном мире искусственный интеллект и машинное обучение становятся неотъемлемой частью многих технологических решений. Одной из наиболее интересных и востребованных задач в этой области. . .
Машинное обучение на Python
bytestream 24.01.2025
Введение в машинное обучение на Python Машинное обучение представляет собой одну из наиболее динамично развивающихся областей информационных технологий, которая позволяет компьютерным системам. . .
Как удалить вирус-майнер с компьютера
hw_wired 24.01.2025
Вирусы-майнеры стали одной из наиболее серьезных угроз для пользователей компьютеров. Эти вредоносные программы тайно используют вычислительные ресурсы зараженного устройства для добычи криптовалюты. . .
Что такое веб-сервер, для чего он нужен и как работает
bytestream 24.01.2025
В современную эпоху цифровых технологий веб-сервер является фундаментальным компонентом интернет-инфраструктуры, обеспечивающим функционирование множества онлайн-сервисов и веб-сайтов. Этот. . .
Как в цикле for перебрать все элементы в словаре в Python
bytestream 24.01.2025
Словари в Python представляют собой мощные структуры данных, которые позволяют хранить информацию в формате ключ-значение. Эта особенность делает их незаменимыми при работе с данными, где требуется. . .
Как отменить rebase в Git
hw_wired 24.01.2025
Git rebase представляет собой мощный инструмент для управления историей коммитов в системе контроля версий Git. Этот механизм позволяет разработчикам изменять последовательность, комбинировать или. . .
Как поменять цвет input placeholder с помощью CSS
bytestream 24.01.2025
В веб-разработке оформление элементов пользовательского интерфейса играет ключевую роль в создании привлекательного и интуитивно понятного дизайна. Особое внимание уделяется формам ввода данных, где. . .
Как перебрать все значения в перечислении (enum) в C#
bytestream 24.01.2025
Перечисление (enum) в языке программирования C# представляет собой специальный тип данных, который позволяет определить набор именованных констант. Этот мощный инструмент особенно полезен, когда. . .
Как обойтись без проверки на null, чтобы избежать NullPointerExce­ption в Java
bytestream 24.01.2025
NullPointerException (NPE) является одним из самых распространенных исключений в Java, создающих серьезные проблемы при разработке программного обеспечения. Данное исключение возникает при попытке. . .
Что лучше использовать в href ссылок в JavaScript: "#" или "javascript:voi­­d(0)­"
bytestream 24.01.2025
При разработке веб-приложений важную роль играет правильное использование HTML-ссылок в сочетании с JavaScript. Одним из ключевых аспектов является выбор корректного значения атрибута href для. . .
Как узнать индекс элемента списка по его значению в Python
hw_wired 24.01.2025
При работе с коллекциями данных в Python часто возникает необходимость не только манипулировать элементами списка, но и определять их точное местоположение. Индекс элемента представляет собой. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru