powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Java [игнор отключен] [закрыт для гостей] / Volatile
16 сообщений из 16, страница 1 из 1
Volatile
    #39518239
faustgreen
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: 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.
package threads;

public class Priority {
	
	public static void main(String[] args) {
		Thread.currentThread().setPriority(Thread.MAX_PRIORITY);
		
		Clicker hi = new Clicker(Thread.NORM_PRIORITY + 3);
		Clicker lo = new Clicker(Thread.NORM_PRIORITY - 3);
		
		lo.start();
		hi.start();
		
		try {
			Thread.sleep(1000);
		} catch (InterruptedException e) {
			System.out.println("Главный поток прерван");
		}
		
		lo.stop();
		hi.stop();
		
		try {
			hi.t.join();
			lo.t.join();
		} catch (InterruptedException e) {
			System.out.println("Главный поток прерван");
		}
		System.out.println("Low-priority thread  - " + lo.click);
		System.out.println("High-priority thread - " + hi.click);
	}
	
	static class Clicker implements Runnable{

		long click = 0;
		Thread t;
		private volatile boolean running = true;
		
		public Clicker(int p){
			t = new Thread(this);
			t.setPriority(p);
		}
		
		@Override
		public void run() {
			while(running){
				click++;
			}
		}
		
		public void start(){
			t.start();
		}
		
		public void stop(){
			running = false;
		}
	}
}



Правильно ли мне кажется, что спецификатор volatile здесь лишний? Так как переменная running уникальна для потока (приватная и не статическая), т.е. другой поток не может ее изменить. И мы будем для каждого потока всегда иметь правильное значение этой переменной?
...
Рейтинг: 0 / 0
Volatile
    #39518253
faustgreen
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
При создании двух классов clicker в каждом из них создастся своя переменная running, т.е. в памяти будет 2 переменные running - ведь так же? А volatile подошло бы в случае, если переменная running была бы внешней по отношению к этим двум потокам, например, передавалась бы в конструктор класса clicker, как параметр?
...
Рейтинг: 0 / 0
Volatile
    #39518255
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
faustgreenПравильно ли мне кажется
Нет, не правильно. Поток и класс Thread это не одно и тоже. Класс Thread это Java API для работы с потоками, а не сам поток.
Так вот к вашей переменной running идёт обращение из разных потоков.
Запись происходит в потоке, который исполняет метод main() - в конструкторе и при вызове stop().
А чтение происходит в другом потоке, который вы запустили вызвав метод start().
...
Рейтинг: 0 / 0
Volatile
    #39518257
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
faustgreenПри создании двух классов clicker в каждом из них создастся своя переменная running, т.е. в памяти будет 2 переменные running - ведь так же?
Да.

faustgreenА volatile подошло бы в случае, если переменная running была бы внешней по отношению к этим двум потокам
Классы и объекты это не потоки.
...
Рейтинг: 0 / 0
Volatile
    #39518261
faustgreen
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Спасибо за информацию, пока не до конца все понятно, пойду почитаю чего.
...
Рейтинг: 0 / 0
Volatile
    #39518265
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
faustgreen, замените все обращения к переменной на запись и чтение через свойство (get/set методы).
В геттере и сеттере логируйте имя потока а лучше даже весь дамп стэка потока. Может понятнее будет.
Ну, и добавьте sleep() в ваш while(true).
...
Рейтинг: 0 / 0
Volatile
    #39518344
faustgreen
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вроде разобрался:
1). Потоки, созданные классами hi и lo не могут изменить переменные running друг друга.
2). Метод main может изменять переменную running обоих потоков. Так же как и сами потоки могут менять свою переменную.

авторПоток и класс Thread это не одно и тоже. Класс Thread это Java API для работы с потоками, а не сам поток.

Вот тут у меня наверное были проблемы с пониманием:

Код: 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.
package threads;

public class Test {

	public static void main(String[] args) throws InterruptedException {
		MyThread t = new MyThread();
		t.start();
		
		Thread.sleep(500);
		
		// Раньше думал, что здесь вызывается "метод потока", а на самом деле вызывается метод класса.
		System.out.println("Метод sayName вызванный из метода main класса Test");
		t.sayName();
		
		t.join();
		
		System.out.println("End");
	}

	static class MyThread extends Thread{
		
		@Override
		public void run() {
			System.out.println("Метод sayName вызванный из метода run класса MyThread");
			sayName();
			
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}

		public void sayName(){
			System.out.println("Имя потока - " + Thread.currentThread().getName());
		}
	}
}



Вывод результатов выполнения:
Код: java
1.
2.
3.
4.
5.
Метод sayName вызванный из метода run класса MyThread
Имя потока - Thread-0
Метод sayName вызванный из метода main класса Test
Имя потока - main
End
...
Рейтинг: 0 / 0
Volatile
    #39518350
faustgreen
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: java
1.
2). Метод main может изменять переменную running обоих потоков. Так же как и сами потоки могут менять свою переменную.


* Т.е. Поток, в котором выполняется метод main, может менять значения переменных running в потоках созданных класами hi и lo.
...
Рейтинг: 0 / 0
Volatile
    #39518394
faustgreen
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Правильно ли я понимаю еще один момент по примеру выше:
Если у нас во время выполнения в одном из потоков (или обоих) выскочит exception или error, то главный поток этого не заметит, но при этом итоговый результат будет неверный - счетчик clicker будет иметь значение, которое у него было на момент exception. Т.е. такой код лучше не писать?

Набросал пример, на эту тему:
Код: 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.
package threads;

public class Test {

	public static void main(String[] args) throws InterruptedException{
		Math1 m1 = new Math1();
		Math2 m2 = new Math2();
		
		m1.start();
		m2.start();
		
		m1.join();
		m2.join();
		
		int result = m1.getResult() + m2.getResult();
		System.out.println(result);
	}
	
	static class Math1 extends Thread{
		private int result1 = 1;
		
		int getResult(){
			return result1;
		}
		
		@Override
		public void run() {
			calculate();
		}

		private void calculate(){
			for (int i=2; i<10; i++)
				result1 = result1 * i;
		}
	}
	
	static class Math2 extends Thread{
		private int result2 = 0;
		
		int getResult(){
			return result2;
		}
		
		@Override
		public void run() {
			try {
				calculate();
			} catch (Exception e) {
			}
		}

		private void calculate() throws Exception{
			for (int i=0; i<10000; i++){
				result2 = result2 + i;
				//if (i == 4)
				//	throw new Exception();
			}	
		}
	}
}



Т.е. если даже поток "умрет", класс никуда не денется и его члены будут доступны?
...
Рейтинг: 0 / 0
Volatile
    #39518421
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
faustgreenТ.е. если даже поток "умрет", класс никуда не денется и его члены будут доступны?
Классы это те же объекты, только особые. Все объекты лежат куче. Время жизни объектов это немного отдельная тема от потоков.
...
Рейтинг: 0 / 0
Volatile
    #39518457
Сергей Арсеньев
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
faustgreenто главный поток этого не заметит, но при этом итоговый результат будет неверный - счетчик clicker
поскольку Вы не попросили сделать счетчик волатильным, то главный поток имеет право его видеть любым. Вне зависимости от того, когда там что произошло в другом потоке. :)
Правда на x86* Вы, скорее всего, этого не заметите. :)
...
Рейтинг: 0 / 0
Volatile
    #39520083
no56892
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Сергей Арсеньевfaustgreenто главный поток этого не заметит, но при этом итоговый результат будет неверный - счетчик clicker
поскольку Вы не попросили сделать счетчик волатильным, то главный поток имеет право его видеть любым. Вне зависимости от того, когда там что произошло в другом потоке. :)
Правда на x86* Вы, скорее всего, этого не заметите. :)
Достаточные гарантии видимости(HB) здесь создаёт join. Увидит ровно то, что было перед ексепшеном.
...
Рейтинг: 0 / 0
Volatile
    #39520138
Сергей Арсеньев
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
no56892,

Ну да, слона (join) то я и не заметил.
https://docs.oracle.com/javase/tutorial/essential/concurrency/memconsist.html then all the statements executed by the terminated thread have a happens-before relationship with all the statements following the successful join.
...
Рейтинг: 0 / 0
Volatile
    #39544106
faustgreen
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вычитал еще такую вещь про volatile переменную:
Если поток A записывает или читает volatile -переменную, а впоследствии поток B производит чтение или запись этой переменной, то значение этой переменной, а также всех общих переменных(shared) (даже не volatile ) всегда будут актуальными для потока B (на момент чтения или записи volatile -переменной). Аналогичная ситуация с synchronized блоками или методами.

Возникли вопросы:
1). Если есть 2 общие переменные для 3-х потоков: int a и volatile int b .
-Первый поток записывает новое значение в обе переменных.
-Второй поток сначала читает волатильную переменную, потом обычную.
-Третий поток читает сначала обычную переменную, потом волатильную.
В примере все действия происходят последовательно, сначала отрабатывает поток 1, потом 2, и затем поток 3. В этом случае, если я правильно понимаю: Поток №2 всегда будет видить актуальные значения обеих переменных, а поток №3 всегда будет иметь актуальное значение volatile переменной, но не всегда обычной?

2). Где можно применить описанное выше свойство (актуальная видимость всех переменных при операциях с volatile-переменными)?
...
Рейтинг: 0 / 0
Volatile
    #39544138
vimba
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
faustgreenВычитал еще такую вещь про volatile переменную:
Если поток A записывает или читает volatile -переменную, а впоследствии поток B производит чтение или запись этой переменной, то значение этой переменной, а также всех общих переменных(shared) (даже не volatile ) всегда будут актуальными для потока B
Про запись вообще не известно откуда взятый бред, а что касается чтения, то можно говорить, о том что поток B увидит все изменения в памяти сделанные потоком A , только когда B прочел из volatile именно то что записал туда A , а не что-нибудь другое.
...
Рейтинг: 0 / 0
Volatile
    #39544145
Alexey Tomin
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
faustgreen2). Где можно применить описанное выше свойство (актуальная видимость всех переменных при операциях с volatile-переменными)?

Самый очевидные - флаг "я всё посчитал, можете читать результаты". Флаг - volatile, результаты- обычные переменные.
...
Рейтинг: 0 / 0
16 сообщений из 16, страница 1 из 1
Форумы / Java [игнор отключен] [закрыт для гостей] / Volatile
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]