Нужно что бы два потока параллельно печатали на экран. (Первый поток печатает числа 1,2,3...10 Второй - 100,200,300...1000). Причём вывод должен быть синхронизирован: сначала родительский поток выводит первую строку, затем дочерний первую, затем родительский вторую строку, затем дочерний вторую и т.д.(100,1,200,2,300,3...) Использовать нужно мьютексы.
pthread_mutex_t mut;
void printt(int i){
pthread_mutex_lock(&mut);
cout<<i<<endl;
pthread_mutex_unlock(&mut);
}
void* func(void*){
for(int i=1;i<=10;i++){
printt(i);
}
return 0;
}
int main() {
pthread_mutex_init(&mut,0);
pthread_t tid;
pthread_create(&tid,0,func,0);
for(int i=100;i<=1000;i+=100){
printt(i);
}
pthread_join(tid,0);
pthread_mutex_destroy(&mut);
return 0;
}
Мой код же печатает сначала main поток 100,200... а потом 1,2... Хотя во время отладки программы печатает, как сказано в задании.
Предупреждение: согласно POSIX данное решение даёт UB [1], хотя и, судя по всему, он работает в реализации pthreads от glibc/linux; он приведен лишь для справки/как идея и не должен использоваться. Спасибо @VTT за замечание.
Для решения задачи нужно количество мьютексов равное количеству потоков.
Идея в том, чтобы мьютексы захватывались разными потоками попеременно, т.е. входя в критические секции нужно захватывать свой мьютекс, а при выходе отпускать мьютекс следующего потока. Само собой, перед началом выполнения свободным должен быть отпущен только один мьютекс. В итоге получается нечто следующее:
pthread_mutex_t mut1;
pthread_mutex_t mut2;
void printt1(int i){
pthread_mutex_lock(&mut1);
cout<<i<<endl;
pthread_mutex_unlock(&mut2);
}
void printt2(int i){
pthread_mutex_lock(&mut2);
cout<<i<<endl;
pthread_mutex_unlock(&mut1);
}
void* func(void*){
for(int i=1;i<=10;i++){
printt2(i);
}
return 0;
}
int main() {
pthread_mutex_init(&mut1,0);
pthread_mutex_init(&mut2,0);
pthread_mutex_lock(&mut2);
pthread_t tid;
pthread_create(&tid,0,func,0);
for(int i=100;i<=1000;i+=100){
printt1(i);
}
pthread_join(tid,0);
pthread_mutex_destroy(&mut1);
pthread_mutex_destroy(&mut2);
return 0;
}
Функция printt
печатает локальную переменную i
, к которой у других потоков нет доступа, а синхронизация не ожидает завершения записи предыдущей строки другим потоком. Также полностью отсутствует обработка ошибок.
Без сигналов , чтоб другой поток проснулся неудобно, придумал только сон. Вроде бы пашет. Нужна переменная для знака кому какая очередь.
// g++ -pthread mutex-semaph.cpp
#include <unistd.h>
# include <pthread.h>
# include <iostream>
pthread_mutex_t mut;
int queue = 1 ; // или 2
void printt(int i, int q){
Again :
pthread_mutex_lock(&mut);
if(queue == q) std::cout<<i<<std::endl;
else {
pthread_mutex_unlock(&mut);
sleep(1);
goto Again ; }
queue = 3 - q ;
pthread_mutex_unlock(&mut);
}
void* func(void*){
for(int i=1;i<=10;i++){
printt(i,2);
}
return 0;
}
int main() {
pthread_mutex_init(&mut,0);
pthread_t tid;
pthread_create(&tid,0,func,0);
for(int i=100;i<=1000;i+=100){
printt(i,1);
}
pthread_join(tid,0);
pthread_mutex_destroy(&mut);
return 0;
}
Сделайте разделяемую volatile
переменную и mutex. Присвойте переменной 1, что означает печать будет проводить первый поток. Запустите потоки.
В каждом потоке в цикле захватываете mutex и читаете значение переменной.
Если значение переменной в первом потоке равно 1, то он печатает данные и присваивает переменной 2. Аналогично, второй поток производит печать если значение переменной равно 2, после чего устанавливает ее в 1.
(Обратите внимание, чтение и модификация переменной защищены mutex-ом.)
Затем поток в любом случае снимает блокировку и (для оптимизации эффективности) вызывает pthread_yield.
Конкретно в вашем случае с внешним циклом и анализом очередности печати внутри printt()
(очевидно, с целью не вытаскивать работу с mutex на уровень управления циклом) в этой функции нужно дождаться, пока общая переменная не примет нужного значения.
Впрочем, хватит общих слов. Вот немного модифицированный ваш код из текста вопроса.
avp@avp-ubu1:hashcode$ cat t-seq-pri.c
#ifdef __cplusplus
#include <iostream>
using namespace std;
#else
#define _GNU_SOURCE
#include <stdio.h>
#endif
#include <pthread.h>
pthread_mutex_t mut;
volatile int turn;
void printt(int i, int q){
int pri = 0;
do {
pthread_mutex_lock(&mut);
if (turn == q) {
#ifdef __cplusplus
cout<<i<<endl;
#else
printf("%d\n", i);
#endif
turn = (q == 1 ? 2 : 1);
pri = 1;
}
pthread_mutex_unlock(&mut);
pthread_yield();
} while (!pri);
}
void* func(void *p){
for(int i=1;i<=10;i++){
printt(i, 2);
}
return 0;
}
int main() {
pthread_mutex_init(&mut,0);
pthread_t tid;
turn = 1;
pthread_create(&tid,0,func,0);
for(int i=100;i<=1000;i+=100){
printt(i, 1);
}
pthread_join(tid,0);
pthread_mutex_destroy(&mut);
return 0;
}
avp@avp-ubu1:hashcode$ gcc t-seq-pri.c -pthread -Wall -O3 && ./a.out
100
1
200
2
300
3
400
4
500
5
600
6
700
7
800
8
900
9
1000
10
avp@avp-ubu1:hashcode$
Виртуальный выделенный сервер (VDS) становится отличным выбором
Вопрос на засыпку, кто знает, можно ли перехватить MyException1 в func3?
Не могу авторизоваться с помощью Jsoup для дальнейшего парсингаВ чем проблема можете подсказать? Ниже предоставлен код и HTTP запрос