Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.80/5: Рейтинг темы: голосов - 5, средняя оценка - 4.80
2 / 2 / 0
Регистрация: 07.04.2016
Сообщений: 298

Потоки - синхронизация

15.11.2022, 10:48. Показов 1092. Ответов 18

Студворк — интернет-сервис помощи студентам
Здравствуйте.

Имеем:
1. многопоточность;
2. синхронизация;
3. c++11;
4. Win10 x64;
5. компилятор tdm.

Что не работает:
Синхронизация: не работает основной поток(строчка 33 в коде ниже) после сигнала от второго потока.

Описание к коду:
В майне в консоль выводятся "*", в функции function1 в консоль выводятся "#". Сначала нужно вывести "#" затем вывести "*". В майне, основной поток создает другой и запускает в работу function1, при этом сам переходит в режим ожидания сигнала, после которого продолжает работать.

Код:
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
#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <chrono>
 
using namespace std;
 
mutex MUTEX1;
condition_variable CONDITION_VARIBLE1;
 
void function1 () {
    unique_lock<mutex> uniqueLock1 (MUTEX1);
 
    for (int i = 1; i < 5; ++i) {
        cout << "# \t" << "[t " << this_thread::get_id() << "]" << endl;
        this_thread::sleep_for(std::chrono::milliseconds (500));
    }
 
    uniqueLock1.unlock();
    CONDITION_VARIBLE1.notify_one ();
 
    this_thread::sleep_for(std::chrono::milliseconds (500));
}
 
int main () {
    thread t1 (function1);
    t1.detach ();
 
    this_thread::sleep_for(std::chrono::seconds (1)); // Что бы t1 успел взять мьютекс.
 
    unique_lock<mutex> uniqueLock1 (MUTEX1);
    CONDITION_VARIBLE1.wait (uniqueLock1);
 
    for (int i = 1; i < 5; ++i) {
        cout << "* \t" << "[t " << this_thread::get_id() << "]" << endl;
        this_thread::sleep_for(std::chrono::milliseconds (500));
    }
 
    return 0;
}
Вопросы:
1. Где я ошибся ?
2. Как реализовать задуманный мной код(максимально просто) ?
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
15.11.2022, 10:48
Ответы с готовыми решениями:

Что такое потоки ввода, потоки вывода?
Здарова всем! Не так давно уже прогаю на С++ и все НИКАК не могу понять, что такое потоки ввода, потоки вывода..! вот допустим...

Потоки и их синхронизация в WinAPI
Доброго времени суток. Начала разбираться с потоками в Win32 . Сразу возникло много вопросов . Собственно хотел реализовать...

Класс Thread, потоки синхронизация потоков и т.д
Имеется код: Модуль Unit1.cpp (в нем запускается поток) //------------------------------------------------------ //... ...

18
 Аватар для zayats80888
6352 / 3523 / 1428
Регистрация: 07.02.2019
Сообщений: 8,995
15.11.2022, 11:03
Цитата Сообщение от Palich Посмотреть сообщение
1. Где я ошибся ?
1. Нет защиты от ложного пробуждения.
2. Нет защиты от невозможности пробуждения (notify случится раньше, чем основной поток встанет в ожидание, ваши "слипы" ничего не гарантируют)
Цитата Сообщение от Palich Посмотреть сообщение
Как реализовать задуманный мной код(максимально просто) ?
Добавить флаг, проверяемый в основном потоке в цикле ожидания, и выставляемый в дополнительном потоке перед уведомлением.

C++
1
2
3
4
5
6
7
8
// дополнительный поток:
flag = true;
uniqueLock1.unlock();
CONDITION_VARIBLE1.notify_one ();
 
// основной поток:
while (!flag)
  CONDITION_VARIBLE1.wait (uniqueLock1);
1
2 / 2 / 0
Регистрация: 07.04.2016
Сообщений: 298
15.11.2022, 19:09  [ТС]
спасибо !
0
2 / 2 / 0
Регистрация: 07.04.2016
Сообщений: 298
16.11.2022, 10:25  [ТС]
так, нет, не спасибо )

Решил сделать прогу чуть сложнее и то же самое. Пробовал разобраться в мануалах, что-то понял, что-то нет, в итоге каша в голове.

Как я понял конструкция
C++
1
CONDITION_VARIBLE1.wait (uniqueLock1, [] () { return BOOL1;});
равносильна конструкции
C++
1
2
3
while ( ! BOOL1) {
    CONDITION_VARIBLE1.wait (uniqueLock1);
}
А теперь что не работает:
Сделал 2 проги: одна с whie, другая с .wait.
Логика такая же как и в первом сообщении, разница в том, что после окончания работы в function1, в майне еще раз выводятся звездочки, потом в function1 еще раз выводятся решетки.

Код с while
Работа останавливается на строчке 69.
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
#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <chrono>
 
using namespace std;
 
mutex MUTEX1;
condition_variable CONDITION_VARIBLE1;
bool BOOL1 = false;
bool BOOL2 = false;
 
void function1 () {
    unique_lock<mutex> uniqueLock1 (MUTEX1);
    BOOL1 = false;
 
    for (int i = 1; i < 5; ++i) {
        cout << " # \t" << " [t " << this_thread::get_id() << "]" << endl;
        this_thread::sleep_for(std::chrono::milliseconds (500));
    }
 
    BOOL1 = true;
    uniqueLock1.unlock();
    CONDITION_VARIBLE1.notify_one ();
 
    while ( ! BOOL2) {
        CONDITION_VARIBLE1.wait (uniqueLock1);
    }
 
    uniqueLock1.lock();
    BOOL2 = false;
 
    for (int i = 1; i < 5; ++i) {
        cout << " # \t" << " [t " << this_thread::get_id() << "]" << endl;
        this_thread::sleep_for(std::chrono::milliseconds (500));
    }
 
    BOOL1 = true;
    uniqueLock1.unlock();
    CONDITION_VARIBLE1.notify_one ();
}
 
int main () {
    thread t1 (function1);
    t1.detach ();
 
    unique_lock<mutex> uniqueLock1 (MUTEX1);
 
    while ( ! BOOL1) {
        CONDITION_VARIBLE1.wait (uniqueLock1);
    }
 
    BOOL1 = false;
 
    for (int i = 1; i < 5; ++i) {
        cout << "* \t" << "[t " << this_thread::get_id() << "]" << endl;
        this_thread::sleep_for(std::chrono::milliseconds (500));
    }
 
    BOOL2 = true;
    uniqueLock1.unlock();
    CONDITION_VARIBLE1.notify_one ();
 
    while ( ! BOOL1) {
        CONDITION_VARIBLE1.wait (uniqueLock1);
    }
 
    uniqueLock1.lock();
    cout << "END" << endl;
    uniqueLock1.unlock();
 
    return 0;
}
Код с .wait
Работа останавливается на строчке 58.
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
#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <chrono>
 
using namespace std;
 
mutex MUTEX1;
condition_variable CONDITION_VARIBLE1;
bool BOOL1 = false;
bool BOOL2 = false;
 
void function1 () {
    unique_lock<mutex> uniqueLock1 (MUTEX1);
 
    for (int i = 1; i < 5; ++i) {
        cout << " # \t" << " [t " << this_thread::get_id() << "]" << endl;
        this_thread::sleep_for(std::chrono::milliseconds (500));
    }
 
    BOOL1 = true;
    uniqueLock1.unlock();
    CONDITION_VARIBLE1.notify_one ();
 
    CONDITION_VARIBLE1.wait (uniqueLock1, [] () { return BOOL2;});
    uniqueLock1.lock();
    BOOL2 = false;
 
    for (int i = 1; i < 5; ++i) {
        cout << " # \t" << " [t " << this_thread::get_id() << "]" << endl;
        this_thread::sleep_for(std::chrono::milliseconds (500));
    }
 
    BOOL1 = true;
    uniqueLock1.unlock();
    CONDITION_VARIBLE1.notify_one ();
}
 
int main () {
    thread t1 (function1);
    t1.detach ();
 
    unique_lock<mutex> uniqueLock1 (MUTEX1);
    CONDITION_VARIBLE1.wait (uniqueLock1, [] () { return BOOL1;});
    BOOL1 = false;
 
    for (int i = 1; i < 5; ++i) {
        cout << "* \t" << "[t " << this_thread::get_id() << "]" << endl;
        this_thread::sleep_for(std::chrono::milliseconds (500));
    }
 
    BOOL2 = true;
    uniqueLock1.unlock();
    CONDITION_VARIBLE1.notify_one ();
 
    CONDITION_VARIBLE1.wait (uniqueLock1, [] () { return BOOL1;});
    uniqueLock1.lock();
 
    for (int i = 1; i < 5; ++i) {
        cout << "* \t" << "[t " << this_thread::get_id() << "]" << endl;
        this_thread::sleep_for(std::chrono::milliseconds (500));
    }
 
    return 0;
}
0
 Аватар для zayats80888
6352 / 3523 / 1428
Регистрация: 07.02.2019
Сообщений: 8,995
16.11.2022, 10:34
Palich, в коде UB.
Для функций condition_variable::wait аргумен lock должен удерживать блокировку.
У вас же она снимется в строках 23 и 54.
Вообще избавьтесь от ручного блокирования/разблокирования.
0
2 / 2 / 0
Регистрация: 07.04.2016
Сообщений: 298
16.11.2022, 19:19  [ТС]
condition_variable::wait аргумен lock должен удерживать блокировку.
эм... допустим, пока не понял зачем мне это.

У вас же она снимется в строках 23 и 54.
да, все верно, для моего понимания на данный момент: я снимаю блокировку в строчке 23, тем самым освобождая мьютекс, что бы в майне произошел захват и блокировка этого мьютекса для того что бы код, который выводит "*" был типа защищен. И так же снимаю блокировку в строке 54 что бы дать возможность захватить мьютекс в "function1".

Вообще избавьтесь от ручного блокирования/разблокирования.
Ух, сложно, мое сознание спокойно когда я вижу явное управление... тем более тут, ну мне так проще на данный момент моего днищенского уровня понять кодм где "стоп" где "старт".
0
19497 / 10102 / 2461
Регистрация: 30.01.2014
Сообщений: 17,808
16.11.2022, 19:26
Цитата Сообщение от Palich Посмотреть сообщение
я снимаю блокировку в строчке 23, тем самым освобождая мьютекс, что бы в майне произошел захват и блокировка этого мьютекса для того что бы код, который выводит "*" был типа защищен.
Самая большая беда когда программист начинает придумывать ожидаемое поведение.
Просто прочитайте документацию. Не надо придумывать.
https://en.cppreference.com/w/... iable/wait
lock - an object of type std::unique_lock<std::mutex>, which must be locked by the current thread
0
2 / 2 / 0
Регистрация: 07.04.2016
Сообщений: 298
16.11.2022, 22:16  [ТС]
я тупой...

Когда мне нужно реализовать одну синхронизацию, то все работает, когда хочу реализовать 3 синхронизации то не работает.
Я не понимаю.
Можете написать код? попробую через код понять, конечно, не самый лучший способ, но другого выходя я не вижу.

код, в котором не могу сделать 3 синхронизации(места где сделать синхронизацию я закомментировал):
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
#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
 
using namespace std;
 
void function1 () {
 
    for (int i = 1; i < 5; ++i) {
        cout << " # \t" << " [t " << this_thread::get_id() << "]" << endl;
        this_thread::sleep_for(std::chrono::milliseconds (300));
    }
 
    // Ждать пока в main выведутся * из первого цикла.
 
    for (int i = 1; i < 5; ++i) {
        cout << " # \t" << " [t " << this_thread::get_id() << "]" << endl;
        this_thread::sleep_for(std::chrono::milliseconds (300));
    }
 
}
 
int main () {
    thread t1 (function1);
    t1.detach ();
 
    // Ждать пока в function выведутся # из первого цикла.
 
    for (int i = 1; i < 5; ++i) {
        cout << "* \t" << "[t " << this_thread::get_id() << "]" << endl;
        this_thread::sleep_for(std::chrono::milliseconds (300));
    }
 
    // Ждать пока в function выведутся # из второго цикла.
 
    for (int i = 1; i < 5; ++i) {
        cout << "* \t" << "[t " << this_thread::get_id() << "]" << endl;
        this_thread::sleep_for(std::chrono::milliseconds (300));
    }
 
    return 0;
}
0
 Аватар для zayats80888
6352 / 3523 / 1428
Регистрация: 07.02.2019
Сообщений: 8,995
16.11.2022, 22:45
Palich,
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
#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
 
using namespace std;
 
struct sync
{
    std::mutex m_mtx;
    std::condition_variable m_cv;
    bool m_order = false;
 
    void wait(bool order)
    {
        std::unique_lock<std::mutex> lock(m_mtx);
        while (m_order != order)
            m_cv.wait(lock);
    }
 
    void post(bool order)
    {
        std::unique_lock<std::mutex> lock(m_mtx);
        m_order = order;
        m_cv.notify_one();
    }
};
 
void function1 (sync& s) {
    
    //s.wait(false);
 
    for (int i = 1; i < 5; ++i) {
        cout << " # \t" << " [t " << this_thread::get_id() << "]" << endl;
        this_thread::sleep_for(std::chrono::milliseconds (300));
    }
    
    s.post(true);
    // Ждать пока в main выведутся * из первого цикла.
    s.wait(false);
 
    for (int i = 1; i < 5; ++i) {
        cout << " # \t" << " [t " << this_thread::get_id() << "]" << endl;
        this_thread::sleep_for(std::chrono::milliseconds (300));
    }
 
    s.post(true);
}
 
int main () {
    sync s;
 
    thread t1 (function1, std::ref(s));
    //t1.detach ();
 
    // Ждать пока в function выведутся # из первого цикла.
    s.wait(true);
 
    for (int i = 1; i < 5; ++i) {
        cout << "* \t" << "[t " << this_thread::get_id() << "]" << endl;
        this_thread::sleep_for(std::chrono::milliseconds (300));
    }
    
    s.post(false);
    // Ждать пока в function выведутся # из второго цикла.
    s.wait(true);
 
    for (int i = 1; i < 5; ++i) {
        cout << "* \t" << "[t " << this_thread::get_id() << "]" << endl;
        this_thread::sleep_for(std::chrono::milliseconds (300));
    }
    
    t1.join();
    return 0;
}
А вообще, в с++20 семафоры подвезли.
0
2 / 2 / 0
Регистрация: 07.04.2016
Сообщений: 298
18.11.2022, 10:32  [ТС]
Понял что, у "уникального блокировщика" и подход уникальный: есть метод ".unlock()", который мне не получилось использовать. Еще уникальность в том, что мой шаблон кода работает в случае если "уникальный блокировщик" принудительно поместить в "зону видимости" т.е. в {} и когда он выходит из этой зоны(понял из вашего кода + статьи в интернетах всяких ), то деструктор сделал то, что мне было нужно. Возникает вопрос, зачем тогда нужен ".unlock()" ?
Такое ощущение что unique_lock "одноразовый".

Решил пока поместить тему с unique_lock у себя в папку "не понято" и реализовал свой код через простейший вид:
C++
1
2
3
4
5
6
7
while ( ! BOOL2) {
    // Wait...
}
MUTEX1.lock();
    ...
    ...
MUTEX1.unlock();
По поводу вашего кода со структурой: Ок, понял, и вроде как одна моя прямая извилина чуть согнулась, но мне показалось городить структуру ради 3х простых действий есть мудреный способ. Но я только учусь, наверное я круто ошибаюсь.

Добавлено через 31 секунду
Цитата Сообщение от zayats80888 Посмотреть сообщение
А вообще, в с++20 семафоры подвезли.
мне бы 11й освоить...
0
19497 / 10102 / 2461
Регистрация: 30.01.2014
Сообщений: 17,808
18.11.2022, 11:00
Цитата Сообщение от Palich Посмотреть сообщение
но мне показалось городить структуру ради 3х простых действий есть мудреный способ.
Выделить абстракцию и использовать ее, вместо размазывания деталей реализации по всему коду - это нормальный, профессиональный подход.

Добавлено через 1 минуту
Цитата Сообщение от Palich Посмотреть сообщение
зачем тогда нужен ".unlock()" ?
Для ручного управления в сложных ситуациях.

Добавлено через 1 минуту
Цитата Сообщение от Palich Посмотреть сообщение
тему с unique_lock
"Тема с unique_lock" прямым образом вытекает из основополагающей для каждого С++ программиста темы RAII.
1
 Аватар для zayats80888
6352 / 3523 / 1428
Регистрация: 07.02.2019
Сообщений: 8,995
18.11.2022, 11:28
Цитата Сообщение от Palich Посмотреть сообщение
Решил пока поместить тему с unique_lock у себя в папку "не понято" и реализовал свой код через простейший вид
А что там под
Цитата Сообщение от Palich Посмотреть сообщение
// Wait...
подразумевается?
Ну и не атомарная проверка флага - UB.

А еще я посмотрел другие ваши темы, и хочу сказать, что в контексте GUI приложения ваша "задумка" не сработает.
Нельзя ставить GUI поток в ожидание таких примитивах синхронизации, это "повесит" приложение.
Как правильно там указал DrOffset, вам нужно изучить тему событий и организовать взаимодействие через события фреймворка wxWidgets.

Не по теме:

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

0
 Аватар для Kuzia domovenok
4268 / 3327 / 926
Регистрация: 25.03.2012
Сообщений: 12,532
Записей в блоге: 1
18.11.2022, 11:47
Цитата Сообщение от Palich Посмотреть сообщение
но мне показалось городить структуру ради 3х простых действий есть мудреный способ.
в таком случае понятно, почему вам кажется, что и unique_lock тоже не нужен.
Действительно, можно вообще никаких локов не городить, а писать

C++
1
2
3
4
5
6
7
8
9
void function()
{
//unique_lock<std::mutex> lock(m_mtx);
m_mtx.lock();
.....
.....
.....
m_mtx.unlock();
}
код полностью рабочий, но так никто не делает, потому что unique_lock это очень хорошая структура с конструктором и деструктором, которую нагородили для 2х простых действий
0
2 / 2 / 0
Регистрация: 07.04.2016
Сообщений: 298
18.11.2022, 21:42  [ТС]
Цитата Сообщение от zayats80888 Посмотреть сообщение
А что там под
там ничего, я просто запустил бесконечный цикл для потока.

Цитата Сообщение от zayats80888 Посмотреть сообщение
Ну и не атомарная проверка флага - UB.
что это значит ? я не знаю.

Цитата Сообщение от zayats80888 Посмотреть сообщение
Нельзя ставить GUI поток в ожидание таких примитивах синхронизации, это "повесит" приложение.
а я поставлю в ожидание поток, который выполняет другой код. Основной поток в это время показывает пользователю диалоговое окно.

Цитата Сообщение от zayats80888 Посмотреть сообщение
изучить тему событий и организовать взаимодействие через события фреймворка wxWidgets.
Изучил, написал, сейчас проблема в синхронизации потоков.

Цитата Сообщение от zayats80888 Посмотреть сообщение
Я бы мог набросать вам простенькую реализацию
спасибо, пока не нужно. Пока бьюсь своим мозгом об эту науку. Пишу на форумы когда не могу своими силами решить задачу.
0
 Аватар для zayats80888
6352 / 3523 / 1428
Регистрация: 07.02.2019
Сообщений: 8,995
18.11.2022, 21:43
Цитата Сообщение от Palich Посмотреть сообщение
там ничего, я просто запустил бесконечный цикл для потока
Ужас!!!
Цитата Сообщение от Palich Посмотреть сообщение
что это значит ? я не знаю
Неопределенное поведение.
Программа может делать не то, что вы от неё ожидаете.
0
 Аватар для SmallEvil
4086 / 2975 / 813
Регистрация: 29.06.2020
Сообщений: 11,000
18.11.2022, 22:46
zayats80888, а почему нельзя принудительно завершить поток (например который по определенной причине ушел в тот же бесконечный цикл или ожидает чего то) ?
Или можно ?
0
 Аватар для zayats80888
6352 / 3523 / 1428
Регистрация: 07.02.2019
Сообщений: 8,995
18.11.2022, 22:57
Цитата Сообщение от SmallEvil Посмотреть сообщение
а почему нельзя принудительно завершить поток
В с++ нет таких средств. Если только "прибить" его ситемным API, однако в контексте с++ приложения это может повлечь UB и утечку ресурсов.
И под ужасом я подразумевал неуместный busy loop без продвинутой стратегии (есть спец. инструкции для режима активного ожидания процессора, снижающие нагрузку на него, или хотя бы тот же yield)
0
2 / 2 / 0
Регистрация: 07.04.2016
Сообщений: 298
20.11.2022, 18:35  [ТС]
Цитата Сообщение от DrOffset Посмотреть сообщение
основополагающей для каждого С++ программиста темы RAII.
загрузил в голову, придется переучиваться, к тому же уже столько кода написал с ручным управлением мьютекса ууу.... вместо многострочек(lock_guard и unique_lock) всего 2: .lock() и unlock()

Цитата Сообщение от DrOffset Посмотреть сообщение
Для ручного управления в сложных ситуациях.
а нельзя промоделировать эту самую сложную ситуацию в шаблонном коде, который я написал ? просто посмотреть. Обязуюсь не использовать ручное управление, буду использовать RAII подход.

Цитата Сообщение от zayats80888 Посмотреть сообщение
Я бы мог набросать вам простенькую реализацию
wxWidgets + multithreading + custom event
0
19497 / 10102 / 2461
Регистрация: 30.01.2014
Сообщений: 17,808
20.11.2022, 19:00
Цитата Сообщение от Palich Посмотреть сообщение
а нельзя промоделировать эту самую сложную ситуацию в шаблонном коде, который я написал ?
Думаю, что нельзя. Потому что эта сложная ситуация будет комбинацией величины проекта, наслоений легаси в нем и сиюминутных требований к коду.
В смысле можно конечно написать что-то такое:
C++
1
2
3
4
5
6
    unique_lock<mutex> uniqueLock(mutex);
    // какая-то работа, которую необходимо выполнить под локом 
    uniqueLock.unlock();
    // еще какая-то работа, которую необходимо выполнить НЕ под локом
    uniqueLock.lock();
    condvar.wait(uniqueLock, [] () { return condition; });
Но в отрыве от задачи это будет выглядеть просто притягиванием за уши.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
20.11.2022, 19:00
Помогаю со студенческими работами здесь

Синхронизация (потоки)
Здравствуйте, есть вот такое вот задание: Разработать программу, которая запускает новый поток при нажатии левой клавиши мыши. Поток...

Потоки/Синхронизация
Всем доброго времени суток. Самостоятельно пытаюсь изучить Java. Занимаюсь по книге Шилдта(Java 8). Дойдя до потоков у меня возник...

Потоки и синхронизация
Задание. Первый поток Server, кидает пакеты (числа) в очередь, с интервалом в пол секунды (500) . Второй поток Client, выводить пакеты...

Потоки. Синхронизация потоков.
Нужно синхронизировать действия потоков, например в доступе к переменной &quot;а&quot;. Где ставить локеры: в потоках, где мы будем изменять...

Потоки. Синхронизация потоков
Доброе время суток! Возникло недопонимание темы потоков. Набросал упрощенный вариант моей задачи (без потоков): using System; ...


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

Или воспользуйтесь поиском по форуму:
19
Ответ Создать тему
Новые блоги и статьи
SDL3 для Web (WebAssembly): Обработчик клика мыши в браузере ПК и касания экрана в браузере на мобильном устройстве
8Observer8 02.02.2026
Содержание блога Для начала пошагово создадим рабочий пример для подготовки к экспериментам в браузере ПК и в браузере мобильного устройства. Потом напишем обработчик клика мыши и обработчик. . .
Философия технологии
iceja 01.02.2026
На мой взгляд у человека в технических проектах остается роль генерального директора. Все остальное нейронки делают уже лучше человека. Они не могут нести предпринимательские риски, не могут. . .
SDL3 для Web (WebAssembly): Вывод текста со шрифтом TTF с помощью SDL3_ttf
8Observer8 01.02.2026
Содержание блога В этой пошаговой инструкции создадим с нуля веб-приложение, которое выводит текст в окне браузера. Запустим на Android на локальном сервере. Загрузим Release на бесплатный. . .
SDL3 для Web (WebAssembly): Сборка C/C++ проекта из консоли
8Observer8 30.01.2026
Содержание блога Если вы откроете примеры для начинающих на официальном репозитории SDL3 в папке: examples, то вы увидите, что все примеры используют следующие четыре обязательные функции, а. . .
SDL3 для Web (WebAssembly): Установка Emscripten SDK (emsdk) и CMake для сборки C и C++ приложений в Wasm
8Observer8 30.01.2026
Содержание блога Для того чтобы скачать Emscripten SDK (emsdk) необходимо сначало скачать и уставить Git: Install for Windows. Следуйте стандартной процедуре установки Git через установщик. . . .
SDL3 для Android: Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 29.01.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами. Версия v3 была полностью переписана на Си, в. . .
Инструменты COM: Сохранение данный из VARIANT в файл и загрузка из файла в VARIANT
bedvit 28.01.2026
Сохранение базовых типов COM и массивов (одномерных или двухмерных) любой вложенности (деревья) в файл, с возможностью выбора алгоритмов сжатия и шифрования. Часть библиотеки BedvitCOM Использованы. . .
SDL3 для Android: Загрузка PNG с альфа-каналом с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 28.01.2026
Содержание блога SDL3 имеет собственные средства для загрузки и отображения PNG-файлов с альфа-каналом и базовой работы с ними. В этой инструкции используется функция SDL_LoadPNG(), которая. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru