88 / 88 / 80
Регистрация: 25.08.2013
Сообщений: 337
1

Кеширование значения указателя потоками

22.02.2018, 18:45. Показов 991. Ответов 3
Метки нет (Все метки)

Доброго дня.
Возник вопрос, возможна ли ситуация кеширования значения указателя (адреса) потоком?
Ситуация, есть два потока, есть два ресурса, доступ к ресурсам через указатели. Один поток формирует (наполняет) ресурс, другой поток вычитывает из ресурса и чистит его. Соответственно, когда второй поток выполнил свою работу (считал и почистил ресурс) он просит второй через атомарный флаг поменять местами значения указателей на ресурсы, тем самым получить наполненный ресурс. Когда первый поток меняет местами значения указателей (отдает ресурс), меняет атомарный флаг обратно. И цикл повторяется.

В данном контексте может ли после swap() второй поток (который читает) не узнать об изменении его указателя ptr_reader?
И вообще безопасен ли данный подход доступа к ресурсам, если нет, как лучше?

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
#include <iostream>
#include <thread>
#include <string>
#include <map>
#include <atomic>
 
using map_type = std::map<std::string, int>;
 
std::atomic_bool flag_switch(false);
map_type mp1, mp2, *ptr_reader = &mp1, *ptr_worker = &mp2;
 
inline void swap(map_type *&a, map_type *&b)
{
    map_type *c = a;
    a = b;
    b = c;
}
 
void reader()
{
    while (true)
    {
        if (flag_switch)
        {
            std::this_thread::sleep_for(std::chrono::seconds(5));
            continue;
        }
        if (ptr_reader->empty())
        {
            flag_switch = true;
            std::this_thread::sleep_for(std::chrono::seconds(60));          
            continue;
        }
 
        // read *ptr_reader
        ptr_reader->clear();
        flag_switch = true;
        std::this_thread::sleep_for(std::chrono::seconds(60));      
    }
}
 
int main()
{
    std::thread th(reader);
    while (true)
    {
        // get data for ptr_worker, some time work
        // update *ptr_worker ---- ++(*ptr_worker)[data];
 
        if (flag_switch)
        {
            swap(ptr_worker, ptr_reader);
            flag_switch = false;
        }
    }
    th.join();
    return 0;
}
__________________
Помощь в написании контрольных, курсовых и дипломных работ, диссертаций здесь
0
Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
22.02.2018, 18:45
Ответы с готовыми решениями:

Изменение значения указателя
Здравствуйте В коде приведена функция, которая при помощи указателей считывает размер массива и...

Инкрементальное увеличение значения указателя не работает
Сразу скажу, что практической цели никакой нет, просто пытаюсь понять принцип работы изменения...

Работа с потоками, выполняющими методы принимающими значения ссылки
Ребята, как сделать так, чтобы можно было через делегат ParametrizedThreadStart можно было...

Изменение значения указателя при преобразовании типов
Есть класс Child, унаследованный от класса Parent. Наследование обычное, а не множественное. И...

3
What a waste!
1607 / 1299 / 180
Регистрация: 21.04.2012
Сообщений: 2,725
22.02.2018, 19:08 2
delete
0
6 / 6 / 2
Регистрация: 27.08.2017
Сообщений: 28
22.02.2018, 19:11 3
Лучший ответ Сообщение было отмечено yrceus как решение

Решение

Цитата Сообщение от yrceus Посмотреть сообщение
В данном контексте может ли после swap() второй поток (который читает) не узнать об изменении его указателя ptr_reader?
Первый поток после swap пишет в атомарную переменную flag, это release operation.
Второй поток читает flag, т.е. выполняет acquire operation. Если он увидел там false, значит все изменения, сделанные первым потоком, ему видны, т.к. он синхронизировался с первым потоком через атомарную переменную и release-acquire операции над ней.
Так что, вроде, проблем нет.

Цитата Сообщение от yrceus Посмотреть сообщение
И вообще безопасен ли данный подход доступа к ресурсам, если нет, как лучше?
Даже если и безопасен (я проблем не нашёл, но это не значит, что их нет ), то крутиться в busy-циклах (пусть и со sleep-ом), проверяя одну переменную, не самое красивое решение.
Не лучше ли взять thread-safe queue, создать 2 экземпляра очереди: одну для свободных ресурсов, из которой потоки могут брать их для наполнения, а вторую для использованных ресурсов, куда скидывать заполненные и ненужные ресурсы, для очистки?
1
88 / 88 / 80
Регистрация: 25.08.2013
Сообщений: 337
22.02.2018, 19:29  [ТС] 4
Да что-то не совсем понятно как лучше сделать всё. Main поток должен работать, чем быстрее тем лучше, его лочить не хотелось бы ни при каких условиях. А второй поток должен изредка проверять состояние. Второй поток так же может залипнуть (данные сбрасывает по сети), соответственно main не должен переполниться.
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
22.02.2018, 19:29
Помогаю со студенческими работами здесь

Нахождение значения выражения с использованием указателя на функцию
Помогите решить.Суть в нахождении значения выражения с использованием указателя на функцию.При...

Значения startIndex указателя и длины не указывают на действительную строку
Помогите пожалуйста! на это: this-&gt;textBox2-&gt;Text += gcnew System::String(str) + &quot;\r\n&quot;; ругается...

Увеличить длину указателя, не стирая уже записанные туда значения
Кто знает, как это сделать? Например, если в указателе записано 1, 2, 3, 4, 5, то сделать 1, 2, 3,...

Размер указателя на структуру, на целочисленные значения со знаком и без и с плавающей запятой
Пусть имеется некий код: struct test{ char a; double b; int c;


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

Или воспользуйтесь поиском по форуму:
4
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2022, CyberForum.ru