Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
1 / 1 / 0
Регистрация: 03.08.2017
Сообщений: 205

Имеет ли смысл создавать volatile переменную

16.09.2026, 11:08. Показов 15127. Ответов 171

Студворк — интернет-сервис помощи студентам
У меня есть функция
C++
1
2
void getParam(double &param){ //...
}
Вызов написал в таком виде:
C++
1
2
3
//...
{volatile double gain;
getParam((double&)gain);//...
Имеет ли смысл такая конструкция или лучше воспользоваться обычной переменной double?
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
16.09.2026, 11:08
Ответы с готовыми решениями:

1 класс имеет переменную указатель на 2, 2 имеет на 1
Имеется 2 класса. В 1 классе есть переменная-указатель на 2 класс, а во 2 классе есть...

Применение описателя Volatile
Приведите плз пример простой проги с этим описателем а то я не пойму для чего он вообще нужен?В чём...

Пример использования спецификатора volatile
В приложенной картинке (из книги Г.С. Шилдта по C++) есть пример использования спецификатора...

171
352 / 150 / 10
Регистрация: 19.07.2024
Сообщений: 858
22.09.2026, 10:57
Студворк — интернет-сервис помощи студентам
Цитата Сообщение от Aledveu Посмотреть сообщение
Мьютекс в оригинале предоставлялся операционной системой, но потом во многих библиотеках на персоналках был тихо заменён на футекс, который гораздо быстрее. так что не надо его сторониться.
Это всё слова. Я много пишу кода для микроконтроллеров. И видел, что из себя представляет честная реализация мьютекса в исходниках РТОС. Там тонна кода! Значительная часть которого к тому же выполняется внутри критических секций (aka - при запрещённых прерываниях). Если интересно - посмотрите исходники uCOS-III (именно 3-й, а не 2-й: в 3-й разработчики постарались сделать честную реализацию мьютекса, в которой решена проблема инверсии приоритетов; в uCOS-II была упрощенная, нечестная реализация, даже не совсем мьютекс собственно).

Добавлено через 14 минут
Цитата Сообщение от Igor3D Посмотреть сообщение
Неясно зачем нужна такая многопоточность если все задачи (Act1, Act2, Act3, Act4), все равно выполняются последовательно.
Серьёзно???
А когда вы применяете мьютекс или критическую секцию или ещё какое другое средство сериализации доступа к общему разделяемому ресурсу, то как вы думаете - как будут выполняться задачи?
Это называется: Сериализация доступа. Для коей собственно и применяются все обсуждаемые средства синхронизации.
Как вы думаете - для чего созданы все средства межпоточной синхронизации? С какой целью?

Цитата Сообщение от Igor3D Посмотреть сообщение
Тогда напрашивается обобщить на разное число потоков и/или задач, а то как-то совсем бедненько, да и копипаста ф-ции не украшает
Не понял смысла претензии. Пример - это именно пример, демонстрирующий способ синхронизации. Всё ненужное из которого выкинуто. В реальной программе, естественно, код будет много сложнее.

Цитата Сообщение от Igor3D Посмотреть сообщение
Реализация Sleep имеет фиксированное/константное время задержки. Это источник забот, и так Вы признаете что ни на какую оптимальность не претендуете, абы работало.
Я вижу - вы ничего не поняли в том коде. Тогда просто пройдите мимо. Этот код не для вас.

Цитата Сообщение от Igor3D Посмотреть сообщение
Как надо было делать. В многопоточности есть схемы/табии что подходят для массы задач, в том числе и для Вашего примера.
Сначала изучите основы многопоточного программирования и синхронизации. Прежде чем начинать кого-то учить. По вашим постам видно, что вы даже основ не знаете.

Ищите учебник и по пунктам изучайте: какие способы межпоточной синхронизации бывают; какие применимы для задач в пределах одного CPU, а какие - для межъядерной синхронизации; что такое "сериалиализация доступа к разделяемому ресурсу"; поддержка средств синхронизации со стороны архитектуры и системы команд на различных архитектурах; и т.д.
Когда освоите основы, тогда может и сможете понять как работает мой пример. Пока он для вас бесполезен.

Цитата Сообщение от Igor3D Посмотреть сообщение
Хотя, судя по Вашему поведению, это будет не скоро
Да, и диванные эксперты и мамкины теоретики - тоже проходите мимо. Этот пост не для вас.
0
 Аватар для Recrut_rf
392 / 337 / 66
Регистрация: 14.10.2014
Сообщений: 1,538
22.09.2026, 11:53
Так, господа знатоки! Проанализировав данный пример ещё раз

И прочитав ответ jcxz, на мой предыдущий пост

Лично я пришёл к выводу, что размышления, как и пример, предоставленный jcxz, корректны. (Если чё - я ни разу не знаток С++ ) И весь срачдискусс, возникший в данной теме связан исключительно с тем, что
jcxz, размышляет на низком уровне - по сути на уровне программирования bare-metal систем. Ему же оппонируют знатоки высокоуровневого программирования. Отсюда и разногласия.

Потому что пример и комментарии к нему от автора кода, на который я ссылаюсь в данном сообщении - прекрасно будет работать во встроенных системах (а возможно там по-другому и никак не сделать). Но в высокоуровневом современном программировании в системах с полноценной операционкой, где будет полностью выполняться абстрактная модель С++, данный пример категорически неприемлем - то есть некорректен.

P.S. Ага - вижу - вон они - уже стартанули - гнилые помидоры и ссаные тряпки в мою сторону
0
352 / 150 / 10
Регистрация: 19.07.2024
Сообщений: 858
22.09.2026, 13:28
Цитата Сообщение от Recrut_rf Посмотреть сообщение
Но в высокоуровневом современном программировании в системах с полноценной операционкой, где будет полностью выполняться абстрактная модель С++, данный пример категорически неприемлем - то есть некорректен.
Почему?
Цитата Сообщение от Recrut_rf Посмотреть сообщение
И весь срачдискусс
Весь срач тут возник от того, что многие участники мешают в одну кучу мух и котлет. Тема вообще про volatile. Но некоторые зачем-то притягивают сюда за уши мьютексы и пр. Не относящееся никак к теме.
И да - ТС нигде не писал, на какой платформе он программирует. Может быть какая угодно, вплоть до Абдурины.
0
Нарушитель
Эксперт функциональных языков программированияЭксперт С++
6691 / 3079 / 1064
Регистрация: 01.06.2021
Сообщений: 11,872
22.09.2026, 15:43
Цитата Сообщение от jcxz Посмотреть сообщение
Весь срач тут возник от того
На форумах, где пользователи анонимы, иначе и не может быть. Совсем недавно на другом форуме я попал в похожий срач. Писал там некое утверждение А, приходит некий чел, цитирует моё утверждение А и дальше весь свой ответ формирует касательно того, что утверждение B неверное. Когда я тычу пальцем, что мол то, что ты пишешь, это всё прекрасно, но я писал утверждение А, при чем здесь вообще B, которое ты критикуешь, то он отвечает, мол да, я вижу, что ты писал А, но я подумал, что будет полезно написать, что утверждение B неверное. Спрашиваю у него, дурачок, зачем тогда цитируешь моё утверждение А и пишешь, что я не прав? Короче, и так возник срач и я решил просто игнорировать и больше не отвечать. Конечно, дурачок в таких случаях думает, что он победил спор, мол его оппонент сдал заднюю, но мне все равно. Пусть радуется дурачок.

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

Если же вернуться в данную тему, то тут, как по мне, дураков нет (как-никак это приличный форум), но всё же есть некоторые личности с неприятными качествами. По этому поводу можно процитировать одну армянскую притчу:

Злому и ленивому мальчику сказали:
- Ох, ох, человеком ты не станешь!
Прошли годы, а он взял и стал царём, ни больше, ни меньше. Пришёл и сказал:
- Видите…, а говорили…
Ему возразили:
- Не говорили "не станешь царём", говорили "не станешь человеком"!
Перефразируя эту притчу, могу сказать, что можно изучить всю теорию программирования, стать великим программистом, зарабатывать приличные деньги и т.д., но если у того или иного эксперта гнусные качества, то грош цена такому челу. Хотя, сомневаюсь, что тут есть такие великие эксперты. Мой жизненный опыт подсказывает, что по-настоященому умный никогда на каждом шагу не станет говорить, что он умный, сильный не скажет, что он сильный, богатый не скажет, что он богатый и т.д.
Если рассказать немного из моей жизни, то лично знаком со спортсменом с медальками европейского масштаба, который положит в одиночку целую стаю мужиков, но он в жизни такой скромный и даже когда обижают, то он даже не лезет сразу в драку как петух, а мирно объясняет свою правоту. Аналогично, знаком в реальной жизни с очень богатым челом, но по внешнему виду даже не скажешь, что он богач. Одевается опрятно, но без показушных брендов.
0
 Аватар для Recrut_rf
392 / 337 / 66
Регистрация: 14.10.2014
Сообщений: 1,538
22.09.2026, 16:55
Цитата Сообщение от jcxz Посмотреть сообщение
Почему?
потому что вы сами сообщили, что (речь про ваш пример)
Цитата Сообщение от jcxz Посмотреть сообщение
Нормально работает на любой платформе имеющей атомарные операции чтения и записи для типа int (x86, ARM, etc.)
а это (по стандарту С++) как раз обеспечивает конструкция
C++
1
std::atomic<int> state{0};
А не
C++
1
int volatile state = 0;
volatile — (насколько я знаю, но при этом не претендую на истину) - только про запрет оптимизаций компилятора в рамках одного потока. То есть (опять же - как это я понимаю) если есть два потока, то они запросто поломают state, а значит и полагаться на корректность исполнения данного кода уже нельзя.

А вот с
C++
1
std::atomic<int> state{0};
пока один поток читает/пишет, другой его будет ждать. И никаких промежуточных состояний тут быть не может.

Вот как то так.
0
3 / 2 / 1
Регистрация: 21.09.2026
Сообщений: 40
22.09.2026, 18:22
Recrut_rf, согласен с Вашей точкой зрения. У С.Маейрса именно так и и обьяснялась разница между двумя этими вариантами - один для работы с особыми видами памяти и запретом на оптимизации, второй - именно для атомарных операций. И даже было уточнение, что даже если какие-то компиляторы и позволяют использовать volatile переменную в атомарных операциях (и это даже работает), то это не стандартное поведение и надеяться на то, что так будет при компиляции другим компилятором не стоит.
Ну и к примеру, если просмотреть ассемблерный код с инкрементом переменных двух видов, там четко видно, что используются совершенно разные команды, что само по себе наводит на мысль, что это не спроста. Если бы не было разницы, с чего бы компилятору генерировать разный ассемблерный код?

Вот такой простой код
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <atomic>
 
void test1()
{
    std::atomic<int> ai = 0;
    ++ai;
}
 
void test2()
{
    int volatile iv = 0;
    ++iv;
}
 
int main(int arc, char **argv)
{
    return 0;
}
разворачивается вот в это
Assembler
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
    .file   "main.cpp"
    .text
    .globl  _Z5test1v
    .def    _Z5test1v;  .scl    2;  .type   32; .endef
    .seh_proc   _Z5test1v
_Z5test1v:
.LFB298:
    pushq   %rbp
    .seh_pushreg    %rbp
    movq    %rsp, %rbp
    .seh_setframe   %rbp, 0
    subq    $48, %rsp
    .seh_stackalloc 48
    .seh_endprologue
    movl    $0, -4(%rbp)
    leaq    -4(%rbp), %rax
    movq    %rax, %rcx
    call    _ZNSt13__atomic_baseIiEppEv
    nop
    addq    $48, %rsp
    popq    %rbp
    ret
    .seh_endproc
    .globl  _Z5test2v
    .def    _Z5test2v;  .scl    2;  .type   32; .endef
    .seh_proc   _Z5test2v
_Z5test2v:
.LFB302:
    pushq   %rbp
    .seh_pushreg    %rbp
    movq    %rsp, %rbp
    .seh_setframe   %rbp, 0
    subq    $16, %rsp
    .seh_stackalloc 16
    .seh_endprologue
    movl    $0, -4(%rbp)
    movl    -4(%rbp), %eax
    addl    $1, %eax
    movl    %eax, -4(%rbp)
    nop
    addq    $16, %rsp
    popq    %rbp
    ret
    .seh_endproc
    .def    __main; .scl    2;  .type   32; .endef
    .globl  main
    .def    main;   .scl    2;  .type   32; .endef
    .seh_proc   main
main:
.LFB303:
    pushq   %rbp
    .seh_pushreg    %rbp
    movq    %rsp, %rbp
    .seh_setframe   %rbp, 0
    subq    $32, %rsp
    .seh_stackalloc 32
    .seh_endprologue
    movl    %ecx, 16(%rbp)
    movq    %rdx, 24(%rbp)
    call    __main
    movl    $0, %eax
    addq    $32, %rsp
    popq    %rbp
    ret
    .seh_endproc
    .section    .text$_ZNSt13__atomic_baseIiEppEv,"x"
    .linkonce discard
    .align 2
    .globl  _ZNSt13__atomic_baseIiEppEv
    .def    _ZNSt13__atomic_baseIiEppEv;    .scl    2;  .type   32; .endef
    .seh_proc   _ZNSt13__atomic_baseIiEppEv
_ZNSt13__atomic_baseIiEppEv:
.LFB364:
    pushq   %rbp
    .seh_pushreg    %rbp
    movq    %rsp, %rbp
    .seh_setframe   %rbp, 0
    .seh_endprologue
    movq    %rcx, 16(%rbp)
    movq    16(%rbp), %rdx
    movl    $1, %eax
    lock xaddl  %eax, (%rdx)
    addl    $1, %eax
    popq    %rbp
    ret
    .seh_endproc
    .ident  "GCC: (x86_64-posix-seh-rev2, Built by MinGW-W64 project) 12.2.0"
Гуглим что такое lock xaddl и сразу видим разницу.
0
Нарушитель
Эксперт функциональных языков программированияЭксперт С++
6691 / 3079 / 1064
Регистрация: 01.06.2021
Сообщений: 11,872
22.09.2026, 19:32
Цитата Сообщение от SarJohnDoe Посмотреть сообщение
lock xaddl
вроде в стандартной библиотеке std::atomic<T>::fetch_add так работает
0
3 / 2 / 1
Регистрация: 21.09.2026
Сообщений: 40
22.09.2026, 19:43
Цитата Сообщение от Royal_X Посмотреть сообщение
вроде в стандартной библиотеке std::atomic<T>::fetch_add так работает
Возможно, но по коду выше видно, что и простой (как-бы) инкремент разворачивается в итоге именно в такую команду. В отличие от команды для volatile переменной, для которой используется простое копирование.
0
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
13235 / 6867 / 1827
Регистрация: 18.10.2014
Сообщений: 17,400
22.09.2026, 19:50
Цитата Сообщение от SarJohnDoe Посмотреть сообщение
Ну и к примеру, если просмотреть ассемблерный код с инкрементом переменных двух видов, там четко видно, что используются совершенно разные команды, что само по себе наводит на мысль, что это не спроста. Если бы не было разницы, с чего бы компилятору генерировать разный ассемблерный код?
Во что на самом деле разворачивается такой код в GCC и Clang я детально показал в сообщениях 46, 51 и 55 этой темы. А та невероятная феерия, которая вы привели... вы, может быть, дебажную конфигурацию кода смотрели, без оптимизаций?

---

Очевидно, так оно и есть. Зачем?

В реальности ваш код транслируется вот так:

GCC:

Assembler
1
2
3
4
5
6
7
8
9
10
11
"test1()":
        mov     DWORD PTR [rsp-4], 0
        lock add        DWORD PTR [rsp-4], 1
        ret
"test2()":
        mov     DWORD PTR [rsp-4], 0
        add     DWORD PTR [rsp-4], 1
        ret
"main":
        xor     eax, eax
        ret
Clang:

Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
test1():
        mov     dword ptr [rsp - 4], 0
        lock            inc     dword ptr [rsp - 4]
        ret
 
test2():
        mov     dword ptr [rsp - 4], 0
        inc     dword ptr [rsp - 4]
        ret
 
main:
        xor     eax, eax
        ret
То есть ничего нового - различие только в префиксе lock для атомарной переменной, т.е. все в точности так же, как мы уже видели в вышеупомянутых постах. Именно благодаря этому префиксу инкремент для атомарной переменной работает правильно (атомарно), а для volatile - не работает правильно (выполняется неатомарно).
0
3 / 2 / 1
Регистрация: 21.09.2026
Сообщений: 40
22.09.2026, 20:06
Цитата Сообщение от TheCalligrapher Посмотреть сообщение
вы, может быть, дебажную конфигурацию кода смотрели, без оптимизаций?
Это даже не собранный код. Это то, что создает компилятор с флагом -S (то есть стадия препроцессора и стадия компилятора, но без стадий ассемблера и компоновщика). С флагом оптимизации -O3 оно конечно меняется, но использованые команды никуда не исчезают. Если при volatile переменной используется addl, то для atomic - уже lock addl
Assembler
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
.file   "main.cpp"
    .text
    .p2align 4
    .globl  _Z5test1v
    .def    _Z5test1v;  .scl    2;  .type   32; .endef
    .seh_proc   _Z5test1v
_Z5test1v:
.LFB298:
    subq    $24, %rsp
    .seh_stackalloc 24
    .seh_endprologue
    movl    $0, 12(%rsp)
    lock addl   $1, 12(%rsp)
    addq    $24, %rsp
    ret
    .seh_endproc
    .p2align 4
    .globl  _Z5test2v
    .def    _Z5test2v;  .scl    2;  .type   32; .endef
    .seh_proc   _Z5test2v
_Z5test2v:
.LFB302:
    subq    $24, %rsp
    .seh_stackalloc 24
    .seh_endprologue
    movl    $0, 12(%rsp)
    movl    12(%rsp), %eax
    addl    $1, %eax
    movl    %eax, 12(%rsp)
    addq    $24, %rsp
    ret
    .seh_endproc
    .def    __main; .scl    2;  .type   32; .endef
    .section    .text.startup,"x"
    .p2align 4
    .globl  main
    .def    main;   .scl    2;  .type   32; .endef
    .seh_proc   main
main:
.LFB303:
    subq    $40, %rsp
    .seh_stackalloc 40
    .seh_endprologue
    call    __main
    xorl    %eax, %eax
    addq    $40, %rsp
    ret
    .seh_endproc
    .ident  "GCC: (x86_64-posix-seh-rev2, Built by MinGW-W64 project) 12.2.0"
Добавлено через 3 минуты
Цитата Сообщение от TheCalligrapher Посмотреть сообщение
Именно благодаря этому префиксу инкремент для атомарной переменной работает правильно (атомарно), а для volatile - не работает правильно (выполняется неатомарно).
Так я-то как раз с этим и не спорю, напротив, уверен что если даже где-то, с каким-то компилятором volatile переменная и ведет себя как атомарная, то полагаться на то что это правильно и так и должно быть всегда и везде - чревато проблемами.
0
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
13235 / 6867 / 1827
Регистрация: 18.10.2014
Сообщений: 17,400
22.09.2026, 20:17
Цитата Сообщение от SarJohnDoe Посмотреть сообщение
Это даже не собранный код.
А собранный и не нужно. Нас интересует только выход собственно компилятора.

Цитата Сообщение от SarJohnDoe Посмотреть сообщение
уверен что если даже где-то, с каким-то компилятором volatile переменная и ведет себя как атомарная, то полагаться на то что это правильно и так и должно быть всегда и везде - чревато проблемами.
Полностью согласен. О том и речь.

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

Но есть некоторые необучаемые индивидуумы, которым это случайное совпадение - дороже любимого котенка. Им хоть кол на голове теши. Однако это - стандартная ситуация в интернет форумах. Все уже привыкли.
1
Нарушитель
Эксперт функциональных языков программированияЭксперт С++
6691 / 3079 / 1064
Регистрация: 01.06.2021
Сообщений: 11,872
22.09.2026, 21:26
Цитата Сообщение от SarJohnDoe Посмотреть сообщение
то полагаться на то что это правильно и так и должно быть всегда и везде - чревато проблемами
Полагаться вообще ни на что нельзя. На этом форуме немало тем про то, что порой компиляторы (особенно, GCC) даже могут где-то не соответствовать ISO C++, а разрабы годами не исправляют эти баги.

Но вот я смотрю на посты из этой темы (не офтопные, а те, где якобы отвечают), и не могу понять, какая связь с вопросом ТС:

Цитата Сообщение от jykm Посмотреть сообщение
Имеет ли смысл такая конструкция или лучше воспользоваться обычной переменной double?
как же далеко занесло экспертов...

и если что, ТС не какой-то там бот, который создал тему и пропал. Сегодня замечал, как он наблюдал за темой (внизу страницы показывает). Т.е. человек по-прежнему следит за темой и наверное в шоке от того, что тут вообще обсуждают...
0
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
13235 / 6867 / 1827
Регистрация: 18.10.2014
Сообщений: 17,400
22.09.2026, 22:17
Цитата Сообщение от Royal_X Посмотреть сообщение
и если что, ТС не какой-то там бот, который создал тему и пропал. Сегодня замечал, как он наблюдал за темой (внизу страницы показывает). Т.е. человек по-прежнему следит за темой и наверное в шоке от того, что тут вообще обсуждают...
О! Это многое объясняет. ТС задал бессмысленный вопрос, а просьбы уточнить его проигнорировал полностью. Я думал - в чем же тут дело? А оказывается вот оно что: ТС просто находился в таком ШОКЕ!!!, что аж кушать пальцы в клавиши не попадали... Оставалось лишь изменившимся лицом бежать пруду бессильно наблюдать за темой

0
Нарушитель
Эксперт функциональных языков программированияЭксперт С++
6691 / 3079 / 1064
Регистрация: 01.06.2021
Сообщений: 11,872
22.09.2026, 22:49
Цитата Сообщение от TheCalligrapher Посмотреть сообщение
а просьбы уточнить его проигнорировал полностью
Только что увидел 4-й пост. Не ну в таком случае значит всё справедливо. Пусть тогда он сперва уточняет.

Если даже код ТС (кусок которого он показал) работает, то наверное в целом он выглядит так:

0
1980 / 836 / 115
Регистрация: 01.10.2012
Сообщений: 5,225
Записей в блоге: 2
22.09.2026, 23:00
Цитата Сообщение от TheCalligrapher Посмотреть сообщение
C++
1
2
inc     dword ptr [rsp - 4]
ret
То есть ничего нового - различие только в префиксе lock для атомарной переменной, т.е. все в точности так же, как мы уже видели в вышеупомянутых постах. Именно благодаря этому префиксу инкремент для атомарной переменной работает правильно (атомарно), а для volatile - не работает правильно (выполняется неатомарно).
А по-моему нет, в данном конкретном случае оба варианта работают правильно/одинаково. Пусть lock включен, тогда только эта команда inc обновляет ячейку [rsp - 4]. Она становится = 1, хотя на момент начала следующей команды (ret) может стать уже другой, напр 2. Теперь пусть lock выключен, тогда может быть два и более писателей. И после выполнения inc ячейка [rsp - 4] напр может быть = 2. Ну и что, общее число единичек остается верным, сумма тоже. То есть если бы использовались только команды inc/dec, то пример с суммой работал бы верно и без атомиков и локов. Другое дело что без lock не получить возвращаемое инкрементом значение, но здесь оно не используется
0
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
13235 / 6867 / 1827
Регистрация: 18.10.2014
Сообщений: 17,400
22.09.2026, 23:20
Лучший ответ Сообщение было отмечено Igor3D как решение

Решение

Цитата Сообщение от Igor3D Посмотреть сообщение
А по-моему нет, в данном конкретном случае оба варианта работают правильно/одинаково.
Как я уже несколько раз заметил, Алексей1153 в посте #35 привел готовую программу, которую вы можете запустить и собственными глазами увидеть, как это все "работает".

Тут даже программу писать не нужно. Просто бери готовое и запускай! Но нет же - продолжается всякое "по-моему"...

Цитата Сообщение от Igor3D Посмотреть сообщение
Пусть lock включен, тогда только эта команда inc обновляет ячейку [rsp - 4]. Она становится = 1, хотя на момент начала следующей команды (ret) может стать уже другой, напр 2. Теперь пусть lock выключен, тогда может быть два и более писателей. И после выполнения inc ячейка [rsp - 4] напр может быть = 2. Ну и что, общее число единичек остается верным, сумма тоже.
Я не понимаю, что тут может быть не ясно. Команда inc в процессоре, очевидно, реализуется как RMW-последовательность. Если элементы R, M, W выполняются не атомарно как единое целое, то два потока могут прочитать из переменной значение 0 (оба), увеличить его до 1 (оба) и записать обратно в память значение 1 (оба). В результате после двух параллельных инкрементов в переменной не получится ожидаемого правильного значения 2, а получится неправильное значение 1.

Где вам тут видится "верная сумма"?

Цитата Сообщение от Igor3D Посмотреть сообщение
То есть если бы использовались только команды inc/dec, то пример с суммой работал бы верно и без атомиков и локов. Другое дело что без lock не получить возвращаемое инкрементом значение, но здесь оно не используется
Ассемблерный код я приводил. Здесь как раз таки и используются только команды inc/dec. Различие лишь в наличии lock. Без lock результат неправильный, а с lock - правильный. Просто попробуйте и посмотрите своими глазами. Не надо слепо теоретизировать.
0
1980 / 836 / 115
Регистрация: 01.10.2012
Сообщений: 5,225
Записей в блоге: 2
22.09.2026, 23:52
Цитата Сообщение от TheCalligrapher Посмотреть сообщение
Я не понимаю, что тут может быть не ясно. Команда inc в процессоре, очевидно, реализуется как RMW-последовательность. Если элементы R, M, W выполняются неатомарно, то два потока могут прочитать из переменной значение 0 (оба), увеличить его до 1 (оба) и записать обратно в память значение 1 (оба). В результате после двух параллельных инкрементов в переменной не получится ожидаемого правильного значения 2, а получится неправильное значение 1.
Да, Вы правы, только что сам догадался Вот она где, "неатомарность"

Добавлено через 2 минуты

Не по теме:

Цитата Сообщение от TheCalligrapher Посмотреть сообщение
Ассемблерный код я приводил. Здесь как раз таки и используются только команды inc/dec. Различие лишь в наличии lock. Без lock результат неправильный, а с lock - правильный. Просто попробуйте и посмотрите своими глазами. Не надо слепо теоретизировать.
Иногда (и в меру) - надо. Проверить - дело хорошее, но результат скорее "просто запоминается"



Добавлено через 2 минуты

Не по теме:

Цитата Сообщение от TheCalligrapher Посмотреть сообщение
продолжается всякое "по-моему"
Ну вот бывают люди с собственным мнением (пусть иногда ошибочным):)

0
352 / 150 / 10
Регистрация: 19.07.2024
Сообщений: 858
23.09.2026, 13:46
Цитата Сообщение от Recrut_rf Посмотреть сообщение
потому что вы сами сообщили, что (речь про ваш пример)
Так почему мой пример "неприемлем"?
Цитата Сообщение от Recrut_rf Посмотреть сообщение
volatile — (насколько я знаю, но при этом не претендую на истину) - только про запрет оптимизаций компилятора в рамках одного потока. То есть (опять же - как это я понимаю) если есть два потока, то они запросто поломают state, а значит и полагаться на корректность исполнения данного кода уже нельзя.
Приведите последовательность событий, которая может "поломать" по вашему.
При условии, что операции записи и чтения int на платформе - атомарны.

Имхо - такой ситуации просто не существует. А вы страхуетесь от сферических коней в вакууме. Ваш std::atomic<int> нужен для RMW-операций. Коих в моём коде просто нет.
Ну или докажите обратное: Какие команды в какой последовательности должны быть выполнены разными потоками, чтобы это привело к нарушению работы моего кода?

Добавлено через 5 минут
Цитата Сообщение от SarJohnDoe Посмотреть сообщение
даже если какие-то компиляторы и позволяют использовать volatile переменную в атомарных операциях (и это даже работает), то это не стандартное поведение и надеяться на то, что так будет при компиляции другим компилятором не стоит.
И вы тоже: Расскажите - какие именно команды записи и чтения int на платформах x86 или ARM, который может сгенерировать компилятор, вызовут неатомарную модификацию int-переменных?
При условии, что int - выровнена (как в моём коде).
Не надо выдумывать сферических коней в вакууме. Приведите конкретный пример. Если конечно разбираетесь в теме.

Добавлено через 2 минуты
Цитата Сообщение от SarJohnDoe Посмотреть сообщение
Гуглим что такое lock xaddl и сразу видим разницу.
А потом включаем голову и думаем: В чём разница между RMW-операцией (коей является ваша XADDL) и простой операцией записи или чтения.
И не валим с больной головы на здоровую.

Добавлено через 2 минуты
Цитата Сообщение от SarJohnDoe Посмотреть сообщение
volatile переменная и ведет себя как атомарная, то полагаться на то что это правильно и так и должно быть всегда и везде - чревато проблемами.
Я приводил выше пример кода межпоточной синхронизации на volatile-переменных. В чём именно там могут быть "проблемы"?

Добавлено через 2 минуты
Цитата Сообщение от TheCalligrapher Посмотреть сообщение
А атомарное поведение в простых присваиваниях - возможно, но это не более чем баг-о-фича конкретной аппаратной платформы, которая на уровне языка является лишь случайным совпадением.
Да ладно!
Можете привести пример компилятора, который на платформе x86 выполнит неатомарное присваивание выровненной int-переменной?
И как именно он это сделает? Побитово что-ли её присвоит???

Добавлено через 1 минуту
Цитата Сообщение от TheCalligrapher Посмотреть сообщение
Но есть некоторые необучаемые индивидуумы, которым это случайное совпадение
Есть индивидуумы, с гипертрофированным ЧСВ, которые готовы нести любую околесицу, лишь бы не признавать, что они были не правы.
Есть что по делу сказать?
0
3 / 2 / 1
Регистрация: 21.09.2026
Сообщений: 40
23.09.2026, 15:05
Цитата Сообщение от jcxz Посмотреть сообщение
И вы тоже: Расскажите - какие именно команды записи и чтения int на платформах x86 или ARM, который может сгенерировать компилятор, вызовут неатомарную модификацию int-переменных?
При условии, что int - выровнена (как в моём коде).
Не надо выдумывать сферических коней в вакууме. Приведите конкретный пример. Если конечно разбираетесь в теме.
С чего это Вы взяли, что я Вам должен приводить какой-то пример? Я Вам проигрался в карты или что? Меня, по большому счету, совершенно не интересует, что и как Вы применяете в своем коде - это Ваш проект, Ваш код, Вам с ним и разбираться. Я лишь высказал свое мнение по вопросу разницы между двумя типами переменных. С одной стороны, все источники говорят о том, что операции с volatile НЕ атомарны, а с std::atomic<> атомарны. С другой стороны, я вижу, что компилятор генерирует разный ассемблерный код при одинаковых операциях для переменных двух разных типов. Все, мне этого достаточно для того, чтобы сделать вывод, что источники правы и нужно следовать им. Это мое мнение, Вы можете с ним не соглашаться, это Ваше право.
0
 Аватар для Recrut_rf
392 / 337 / 66
Регистрация: 14.10.2014
Сообщений: 1,538
23.09.2026, 15:43
Цитата Сообщение от jcxz Посмотреть сообщение
Приведите последовательность событий, которая может "поломать" по вашему.
При условии, что операции записи и чтения int на платформе - атомарны.

если принять на веру, что операции чтения и записи на платформе атомарны и, используя volatile, образно, говорим компилятору что не надо state никак оптимизировать (ну там не знаю - хранить в регистре, как то в памяти его перекладывать и прочие вещи творить) - тогда да, признаю что код корректен.
И в ваших условиях всё нормально отработает - мы ведь пишем атомарно, читаем атомарно
И вы правы в своих рассуждениях.

НО!!!!!

Но, в чём лично у меня претензии к вам и к вашему коду?
Вы утверждаете, что он абсолютно корректен и нормально отработает. И тут я даже спорить с вами не буду - всё так. Корректно отработает. Но только при тех условиях, которые вы сами перечислили - что в данной системе будут атомарные операции чтения и записи. Но ведь обычный / стандартный / без всяких плагинов расширений и прочих компиляторных фич С++ таких гарантий НЕ ДАЁТ!!!!

А далее - представьте себе (ведь этот раздел форума для начинающих - кто за знаниями сюда приходит) - заходит такой начинающий в эту тему и видит:
"Хммм умные дядьки, шарящие в плюсах, утверждают что volatile нужен для синхронизации между потоками и вообще - полезен в многопоточности, ещё и пример есть, да и куча умных слов: RMW-операцией, XADDL, регистры, ассемблер. Запоминает всё это (в основном крутые и непонятные обозначения да и то - половину Ну и само собой - используешь многопоток - применяй volatile ) А в саму суть нифига не вникает - потому что в потоках срача данной темы не щарящий мало что полезного для себя найдёт" Пойдёт на собес, чувствуя себя "Д'Артаньяном среди плюсов" и лихо так обделается - ЖИДКО, СМАЧНО - МОЖ ДАЖ НА ВСЮ ЖИЗНЬ ЗАПОМНИТ , особенно если будет ссылаться на умных дядек с киберфорума
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
23.09.2026, 15:43

const volatile
Пример из Шилдт Г. &quot;С++ Базовый курс (3-е издание, 2010)&quot; стр 205 const volatile unsigned char...

исследование volatile
Здравствуйте. В университете дали задание: &quot;Исследование квалификаторов volatile и инструкции...

int\ volatile int \ const int
Товарищи, паника! Имеется код: int a = 5; std::cout &lt;&lt; &quot;Init value a: &quot; &lt;&lt; a &lt;&lt; &quot;\n&quot;; ...

const_cast: const и volatile
Как известно const_cast сбрасывает наложенные ограничения при помощи модификаторов const и...

Что такое "volatile int"
есть объявление и инициализация переменной: volatile int Sklad = 0; что такое &quot;volatile&quot;? с msdn...


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

Или воспользуйтесь поиском по форуму:
80
Ответ Создать тему
Новые блоги и статьи
Особенности gif сгенерированных в Си
russiannick 21.10.2026
Рассмотрим генерацию gif файлов, которые в Си имеют свои особенности. Gif представляет собой графический формат популярный в интернете. Посмотрим на палитру. Gif файл сгенерированный в си отличается. . .
FPS контроллер с анимированными Y-Bot и 3D-звуком miniaudio (Box3D, Recast, BehaviorTree.CPP, ozz-animation, ImGui, OpenGL и SDL3)
8Observer8 18.10.2026
Содержание блога | English Version Полное мультиплатформенное руководство по стартовому проекту с FPS-контроллером игрока, анимированными роботами Y-Bot с 4-слойным блендингом, 3D-физикой Box3D,. . .
Локальный http сервер
Argus19 17.10.2026
Локальный http сервер На работе, на двух локальных компьютерах круглосуточно работают программы опроса приборов с записью в книги Excel,которые раз в сутки записываются на сервер компании. Т. к. . . .
Копировать Windows на новый диск на UEFI
damix 17.10.2026
https:/ / uriesk. wordpress. com/ 2016/ 11/ 01/ move-window-10-to-ssd-on-a-uefi-dualboot-system-with-basic-linux-tools/ TL DR Вставляем диск, а старый подключаем через переходник, грузимся с лайва. . .
ИИ не может найти нужный язык в списке
Supersumestria 05.10.2026
Я ему даю вот такое изображение и прошу найти и подчеркнуть немецкий язык. Возвращает он вот это: https:/ / i. **********/ vqBWLe2. png Нужную строчку в 3й колонке просто выдумал. . Это. . .
Новая последняя моя музыка в SUNO
zorxor 05.10.2026
Здравствуйте, дорогие мои друзья! С большой радостью я хотел бы представить вам свою новую последнею музыку, которую сгенерировала мне по моей просьбе нейросеть SUNO. С уважением, zorxor. Это. . .
Программный домашний кинотеатр
russiannick 27.09.2026
Сподобился на программный домашний кинотеатр. В качестве ЯВУ по традиции выбрал js. В помощники взял Яндекс-Алису. Было создано три зала на разные интересы. исторические и ретро сериал Хичкок. . .
Беседа с ИИ о программистах, недопускающих к созданию и правке кода генеративные ИИ и причины этого
zorxor 21.09.2026
Раньше я радовался или получал некоторые эмоции, пусть небольшие, но всё же, от самого процесса написания кода, рекомпиляции и запуска, видя постепенное развитие программы и прочее. А теперь лень. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru