Форум программистов, компьютерный форум, киберфорум
Java
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.63/8: Рейтинг темы: голосов - 8, средняя оценка - 4.63
2 / 2 / 2
Регистрация: 27.09.2013
Сообщений: 51

НЕ понятно volatile

27.09.2013, 16:10. Показов 1585. Ответов 11
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
НЕ могу понять как volatile влияет на видимость.

Вот например код , булево переменная не объявлена как volatile и все нормально работает:
Java
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
package TestOverride;
 
import java.util.concurrent.TimeUnit;
 
public class TestVolatile implements Runnable
{
    protected Controller contr;
    
    public TestVolatile(Controller cont)
    {
        contr = cont;
    }
    
    public static void main(String[] args) throws InterruptedException 
    {
        Controller cont = new Controller(true);
        
        Thread thread = new Thread(new TestVolatile(cont));
        thread.start();
        
        System.out.println("Before Sleep!");
        TimeUnit.SECONDS.sleep(5);
        System.out.println("After Sleep!");
        
        System.out.println("Change Controller!");
        cont.test = false;
        System.out.println("Change Controller finish!");
    }
 
    @Override
    public void run() 
    {
        while(contr.getTest())
        {
            System.out.println("TRUE");
            
 
            try 
            {
                TimeUnit.SECONDS.sleep(1);
                
            } catch (InterruptedException e) 
            {
                e.printStackTrace();
            }
        }
        
    }
    
    public static class Controller
    {
        public Controller(boolean test)
        {
            this.test = test;
        }
        
        public boolean getTest()
        {
            return test;
        }
        
        public void setTest(boolean test)
        {
            this.test = test;
        }
        
        protected boolean test;
    }
    
 
 
 
}
Может кто - нибудь продемонстрировать пример где демонстрируется проблема видимости ?
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
27.09.2013, 16:10
Ответы с готовыми решениями:

И снова volatile. Глобальный массив, изменяемый в обработчике прерывания, должен быть volatile?
Всем привет. Имеется официальный код примера на чип-трансивер nrf24LE1 от Nordic. Keil C51 // Global variables uint8_t...

Заменить volatile на Thread.MemoryBarrier. Код приведён. Как оптимизировать обращения для чтения к volatile полю класса?
Не совсем понятна мне пока что работа Thread.MemoryBarrier. Знаю, что можно оптимизировать обращения к полю _cancellation, смотрел...

как i двигается понятно но вот не понятно как это делает j ?
Здравствуйте, вопрос очень глупы но все же есть цикл for (int i = 0,j = 0; i < source.length; i++) как i двигается понятно но вот не...

11
 Аватар для verylazy
462 / 462 / 71
Регистрация: 26.02.2013
Сообщений: 1,263
27.09.2013, 16:44
Java
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
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
 
import javax.swing.text.html.HTMLDocument.HTMLReader.IsindexAction;
 
public class TestThread {
 
    public static void main(String[] args) throws NumberFormatException, IOException {
 
        BladeRunner br = new BladeRunner();
        Thread t = new Thread(br);
        t.start();
        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
        while (true) {
            System.out.print("Второй поток будет работать пока не введете 0\n");
            Integer number = Integer.valueOf(in.readLine());
            if (number == 0) {
                br.running = false;
            }
        }
    }
}
 
class BladeRunner implements Runnable {
 
    volatile boolean running = true;
 
    @Override
    public void run() {
        while (running) {
        }
        System.out.println("Завершение работы потока");
    }
}
пока переменная volatile - все рабтает
если объявить без этого слова, то остановить поток не получится

и читать это
0
2 / 2 / 2
Регистрация: 27.09.2013
Сообщений: 51
27.09.2013, 17:03  [ТС]
Так почему у меня все работает без volatile ?

Добавлено через 6 минут
Цитата Сообщение от verylazy Посмотреть сообщение
while (running) {
* * * * }
Тут я понял , компилятор просто произвел оптимизацию увидев что в цикле нету операторов вместо обращения к переменной подставил константу true и все...

Добавлено через 5 минут
Решил проверить ваш пример и не фига он не работает ( то есть даже без volatile все выключает)
просто вы в бесконечном цикле читаете консоль:

Java
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
package TestOverride;
 
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
 
 
 
public class TestThread {
 
    public static void main(String[] args) throws NumberFormatException, IOException {
 
        BladeRunner br = new BladeRunner();
        Thread t = new Thread(br);
        t.start();
        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
        while (br.running) { //Тут проблема у вам была
            System.out.print("Второй поток будет работать пока не введете 0\n");
            Integer number = Integer.valueOf(in.readLine());
            if (number == 0) {
                br.running = false;
            }
        }
    }
}
 
class BladeRunner implements Runnable {
 
    boolean running = true;  //Нет не кого volatile
 
    @Override
    public void run() {
        while (running) {
        }
        System.out.println("Завершение работы потока");
    }
}
0
Эксперт Java
 Аватар для turbanoff
4094 / 3828 / 745
Регистрация: 18.05.2010
Сообщений: 9,331
Записей в блоге: 12
27.09.2013, 17:26
Вот пример - без volatile будет работать бесконечно
Java
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
import java.util.concurrent.TimeUnit;
 
public class Main implements Runnable {
    protected Controller contr;
 
    public Main(Controller cont) {
        contr = cont;
    }
 
    public static void main(String[] args) throws InterruptedException {
        Controller cont = new Controller(true);
 
        Thread thread = new Thread(new Main(cont));
        thread.start();
 
        System.out.println("Before Sleep!");
        TimeUnit.SECONDS.sleep(5);
        System.out.println("After Sleep!");
 
        System.out.println("Change Controller!");
        cont.test = false;
        System.out.println("Change Controller finish!");
    }
 
    @Override
    public void run() {
        long i = 0;
 
        while (contr.getTest()) {
            i++;
        }
    }
 
    public static class Controller {
        Controller(boolean test) {
            this.test = test;
        }
 
        boolean getTest() {
            return test;
        }
 
        volatile boolean test;
    }
}
запускаю так, чтобы точно убедиться, что JIT отработал
Code
1
java -server -XX:+PrintCompilation
Ключевая проблема в вашем тесте - что JIT не успевает разогреться (У вас запускается не больше 6 итераций)
0
 Аватар для verylazy
462 / 462 / 71
Регистрация: 26.02.2013
Сообщений: 1,263
27.09.2013, 17:44
ну в бесконечном и что дальше?
второй поток останавливается если ввести 0, или может надо было программу с GUI для примера написать?
0
2 / 2 / 2
Регистрация: 27.09.2013
Сообщений: 51
27.09.2013, 18:39  [ТС]
Цитата Сообщение от verylazy Посмотреть сообщение
пока переменная volatile - все рабтает
если объявить без этого слова, то остановить поток не получится
Ваши слова? так вот я убрал volatile и не фига.

Добавлено через 4 минуты
Цитата Сообщение от turbanoff Посмотреть сообщение
Вот пример - без volatile будет работать бесконечно
Java
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
import java.util.concurrent.TimeUnit;
 
public class Main implements Runnable {
    protected Controller contr;
 
    public Main(Controller cont) {
        contr = cont;
    }
 
    public static void main(String[] args) throws InterruptedException {
        Controller cont = new Controller(true);
 
        Thread thread = new Thread(new Main(cont));
        thread.start();
 
        System.out.println("Before Sleep!");
        TimeUnit.SECONDS.sleep(5);
        System.out.println("After Sleep!");
 
        System.out.println("Change Controller!");
        cont.test = false;
        System.out.println("Change Controller finish!");
    }
 
    @Override
    public void run() {
        long i = 0;
 
        while (contr.getTest()) {
            i++;
        }
    }
 
    public static class Controller {
        Controller(boolean test) {
            this.test = test;
        }
 
        boolean getTest() {
            return test;
        }
 
        volatile boolean test;
    }
}
запускаю так, чтобы точно убедиться, что JIT отработал
Code
1
java -server -XX:+PrintCompilation
Ключевая проблема в вашем тесте - что JIT не успевает разогреться (У вас запускается не больше 6 итераций)
Не понятно всё равно вот пример
Java
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
package TestOverride;
 
import java.util.concurrent.TimeUnit;
 
public class TestVolatile implements Runnable
{
    protected Controller contr;
    
    public TestVolatile(Controller cont)
    {
        contr = cont;
    }
    
    public static void main(String[] args) throws InterruptedException 
    {
        Controller cont = new Controller(true);
        
        Thread thread = new Thread(new TestVolatile(cont));
        thread.start();
        
        System.out.println("Before Sleep!");
        TimeUnit.SECONDS.sleep(20);
        System.out.println("After Sleep!");
        
        System.out.println("Change Controller!");
        cont.test = false;
        System.out.println("Change Controller finish!");
    }
 
    @Override
    public void run() 
    {
        while(contr.getTest())
        {
            System.out.println("TRUE");
            
 
            try 
            {
                //TimeUnit.SECONDS.sleep(1);
                
            } catch (Exception e) 
            {
                e.printStackTrace();
            }
        }
        
    }
    
    public static class Controller
    {
        public Controller(boolean test)
        {
            this.test = test;
        }
        
        public boolean getTest()
        {
            return test;
        }
        
        public void setTest(boolean test)
        {
            this.test = test;
        }
        
        protected boolean test;
    }
    
 
 
 
}
За 20 секунд будет выполнено не меньше миллиона итераций, все равно все прекращается.

Добавлено через 3 минуты
Опять же проверил и ваш пример turbanoff, и все нормально вырубается:

Java
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
package TestOverride;
 
import java.util.concurrent.TimeUnit;
 
public class Main implements Runnable {
    protected Controller contr;
 
    public Main(Controller cont) {
        contr = cont;
    }
 
    public static void main(String[] args) throws InterruptedException {
        Controller cont = new Controller(true);
 
        Thread thread = new Thread(new Main(cont));
        thread.start();
 
        System.out.println("Before Sleep!");
        TimeUnit.SECONDS.sleep(5);
        System.out.println("After Sleep!");
 
        System.out.println("Change Controller!");
        cont.test = false;
        System.out.println("Change Controller finish!");
    }
 
    @Override
    public void run() {
        long i = 0;
 
        while (contr.getTest()) {
            i++;
            System.out.println(i);
        }
    }
 
    public static class Controller {
        Controller(boolean test) {
            this.test = test;
        }
 
        boolean getTest() {
            return test;
        }
 
         boolean test;
    }
}
0
Эксперт Java
 Аватар для turbanoff
4094 / 3828 / 745
Регистрация: 18.05.2010
Сообщений: 9,331
Записей в блоге: 12
27.09.2013, 18:58
Цитата Сообщение от BigBangTheory Посмотреть сообщение
За 20 секунд будет выполнено не меньше миллиона итераций, все равно все прекращается.
Все дело в том, что вы вызываете метод println в цикле:
Код метода PrintStream.println
Java
1
2
3
4
5
6
    public void println(String x) {
        synchronized (this) {
            print(x);
            newLine();
        }
    }
внутри метода стоит synchronized - скорее всего это не нравится оптимизатору JIT-а.
Даже если убрать вызов System.out.println из основного потока, оптимизатор все равно не может гарантировать, что какой-то поток вдруг не вызовет println, и, соответственно, вызов getTest заинлайниться не может.
Как я и говорил - запускайте java с флажком -XX:+PrintCompilation, чтобы убедиться, что JIT хотя бы сработал.
1
2 / 2 / 2
Регистрация: 27.09.2013
Сообщений: 51
27.09.2013, 19:20  [ТС]
Цитата Сообщение от turbanoff Посмотреть сообщение
synchronized
Разве при в входе в синхронайзед блок все переменные в локальном кеше потока не обновляются?
Или это уже другая история?

Добавлено через 2 минуты
Цитата Сообщение от turbanoff Посмотреть сообщение
Даже если убрать вызов System.out.println
Я убрал println все ровно тажа история

Цитата Сообщение от turbanoff Посмотреть сообщение
оптимизатор все равно не может гарантировать, что какой-то поток вдруг не вызовет println, и, соответственно, вызов getTest заинлайниться не может.
Здесь вообще не понял..

Несвязанно все это ли с отношением happenes - before ?
0
Эксперт Java
 Аватар для turbanoff
4094 / 3828 / 745
Регистрация: 18.05.2010
Сообщений: 9,331
Записей в блоге: 12
27.09.2013, 19:43
Цитата Сообщение от BigBangTheory Посмотреть сообщение
Разве при в входе в синхронайзед блок все переменные в локальном кеше потока не обновляются?
Насколько я знаю, в общем случае нет (при входе в synchronized мы обязательно видим только те изменения, которые были сделаны в другом потоке, который был тоже в соответствующем блоке), но скорее всего для x86 это действительно так.
Цитата Сообщение от BigBangTheory Посмотреть сообщение
Здесь вообще не понял..
Ключевой момент - оптмизатор не может заинлайнить/скомпилировать метод run. Почему именно, я могу только предположить
0
2 / 2 / 2
Регистрация: 27.09.2013
Сообщений: 51
27.09.2013, 19:48  [ТС]
Цитата Сообщение от turbanoff Посмотреть сообщение
оптмизатор не может заинлайнить/скомпилировать метод run.
если правильно понял то вы имеете ввиду вставить код функции вместо его вызова?? То есть аналог inline c++?
Так ведь это должно происходит на этапе компиляции ,а не выполнения... или я не прав?
0
Эксперт Java
 Аватар для turbanoff
4094 / 3828 / 745
Регистрация: 18.05.2010
Сообщений: 9,331
Записей в блоге: 12
27.09.2013, 19:51
Цитата Сообщение от BigBangTheory Посмотреть сообщение
Так ведь это должно происходит на этапе компиляции ,а не выполнения... или я не прав?
Имеется ввиду компилирование в native код. В Java, обычно, это происходит во время выполнения.
0
2 / 2 / 2
Регистрация: 27.09.2013
Сообщений: 51
27.09.2013, 20:12  [ТС]
Цитата Сообщение от turbanoff Посмотреть сообщение
Имеется ввиду компилирование в native код. В Java, обычно, это происходит во время выполнения.
Понятно.

Цитата Сообщение от turbanoff Посмотреть сообщение
Насколько я знаю, в общем случае нет (при входе в synchronized мы обязательно видим только те изменения, которые были сделаны в другом потоке, который был тоже в соответствующем блоке), но скорее всего для x86 это действительно так.
Собственно читаю вот эту статью
и есть не большой вопрос , как лучше инициализировать переменную через set-метод объекта который возможно будет использоваться (возможно) из двух и более потоков ? Собственно я мог вообще не создавать эту тему и просто сделать все в sync блоке , но что-то кажется мне для простого присваивания это слишком жирно. Теперь же ваш пример вообще меня запутал ) так как я не знаю доверять мне volatile и вообще нужно ли это.

Ладно буду читать пока )
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
27.09.2013, 20:12
Помогаю со студенческими работами здесь

Volatile
подскажите, как переменную объявить volatile Почему нельзя так сделать volatile uint32_t DataCapture_TIM1=0; Добавлено через 7...

volatile
Давайте внесем ясность и разберемся максимально подробно, что такое volatile. И когда применять это ключевое слово. Что я знаю об этом...

Volatile
еще не понятен модификатор volatile/ не хотел открывать новую тему.

volatile
зачем нужно ключевое слово volatile?

Использование Volatile
В общем, вопрос как его использовать. Есть такой тестовый код: using System; using System.Diagnostics; using System.Threading; ...


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

Или воспользуйтесь поиском по форуму:
12
Ответ Создать тему
Новые блоги и статьи
Оттенки серого
Argus19 18.03.2026
Оттенки серого Нашёл в интернете 3 прекрасных модуля: Модуль класса открытия диалога открытия/ сохранения файла на Win32 API; Модуль класса быстрого перекодирования цветного изображения в оттенки. . .
SDL3 для Desktop (MinGW): Рисуем цветные прямоугольники с помощью рисовальщика SDL3 на Си и C++
8Observer8 17.03.2026
Содержание блога Финальные проекты на Си и на C++: finish-rectangles-sdl3-c. zip finish-rectangles-sdl3-cpp. zip
Символические и жёсткие ссылки в Linux.
algri14 15.03.2026
Существует два типа ссылок — символические и жёсткие. Ссылка в Linux — это запись в каталоге, которая может указывать либо на inode «файла-ИСТОЧНИКА», тогда это будет «жёсткая ссылка» (hard link),. . .
[Owen Logic] Поддержание уровня воды в резервуаре количеством включённых насосов: моделирование и выбор регулятора
ФедосеевПавел 14.03.2026
Поддержание уровня воды в резервуаре количеством включённых насосов: моделирование и выбор регулятора ВВЕДЕНИЕ Выполняя задание на управление насосной группой заполнения резервуара,. . .
делаю науч статью по влиянию грибов на сукцессию
anaschu 13.03.2026
прикрепляю статью
SDL3 для Desktop (MinGW): Создаём пустое окно с нуля для 2D-графики на SDL3, Си и C++
8Observer8 10.03.2026
Содержание блога Финальные проекты на Си и на C++: hello-sdl3-c. zip hello-sdl3-cpp. zip Результат:
Установка CMake и MinGW 13.1 для сборки С и C++ приложений из консоли и из Qt Creator в EXE
8Observer8 10.03.2026
Содержание блога MinGW - это коллекция инструментов для сборки приложений в EXE. CMake - это система сборки приложений. Здесь описаны базовые шаги для старта программирования с помощью CMake и. . .
Как дизайн сайта влияет на конверсию: 7 решений, которые реально повышают заявки
Neotwalker 08.03.2026
Многие до сих пор воспринимают дизайн сайта как “красивую оболочку”. На практике всё иначе: дизайн напрямую влияет на то, оставит человек заявку или уйдёт через несколько секунд. Даже если у вас. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru