Атомарность??
2. Почитайте статью http://www.javenue.info/post/81 и поймите что volatile не панацея и не может заменить собой синхронизацию
3. Чтобы всетаки понять зачем нужно volatile поекспериментируйте с моим примером.
private int value;
/*volatile*/ static long i;
public void run() {
while (true) {
i = value;
}
}
public static void main(String[] args) {
new Atomicity(1).start();
new Atomicity(-1).start();
while (true)
{
long icopy = i;
if (Math.abs(icopy) != 1)
System.out.println(icopy);
}
}
public Atomicity(int value)
{
super();
this.value = value;
}
}
PS/ не уверен будет ли мой пример показательным на 64-битной оси.
А каким боком volatile относится к атомарности?
Он ведь нужен для сквозного чтения/записи значений ("мимо регистров") в многопроцессорных системах.
Вы запускали модифицырованый мной пример?
У меня нет Java-компилятора.
Без volatile у вас может случится что в определенный момент времени 32 бита будет от одного присваивания, а вторая половина от другого.
У меня выводятся в консоль числа 4294967295 (старшие розряды от 1,а младшые от -1)
и наоборот число -4294967295
Если добавить volatile то поле будет присваиватся и читатся атомарно. И в консоль вообще ничего не выведется. Так как в і будет либо 1 либо -1
В примере из статьи volatile не помагает, потому что -- и ++ не атомарные.
На сколько я понимаю, они розкладаются в чтото типа bufer = i; i = bufer+1;
тоесть чтение и запись в i всеровно будут атомарными, а вот на bufer и произойдет розезд значений.
К примеру 2 трида будут вместе делать инкремент при і=0, а в результате присвоится не 2, а только 1.
Это будет из-за отсутствия синхронизации доступа к i, а вовсе не из-за отсутствия volatile.
Нет, а зачем? Мне достаточно посмотреть на него. Там не сотни строк кода.
Ну хорошо. Вот вам сотни строк, хоть кода там не так уж и много.
http://fuseyism.com/classpath/doc/java/util/concurrent/atomic/AtomicLong-source.html
Обратите внимание каким именно образом реализована атомарность.
Насколько я умею читать то для гет и сет достаточно модификатора volatile
Более сложные операцыи наблюдаем только на конструкцыях типа (читать-модифицыровать-присвоить)
Для храбрых душой :). Пока бекдоров не замечено
Появление volatile действительно кажется странным, но это так:
[QUOTE=JVM Spec]
8.4 Nonatomic Treatment of double and long Variables
If a double or long variable is not declared volatile, then for the purposes of load, store, read, and write operations it is treated as if it were two variables of 32 bits each; wherever the rules require one of these operations, two such operations are performed, one for each 32-bit half. The manner in which the 64 bits of a double or long variable are encoded into two 32-bit quantities and the order of the operations on the halves of the variables are not defined by The Java Language Specification.
[/QUOTE]
и тут же
[QUOTE=JVM Spec]
An implementation is free to implement load, store, read, and write operations for double and long values as atomic 64-bit operations; in fact, this is strongly encouraged.
[/QUOTE]
тоесть пример может работать здесь и не работать тут
На практике оно вроде и роботает, а на другой виртуалке может и поломаться.
Кстати в приведенном реббитом коде как раз таки вызываются unsafe конструкции, использующие судя по всему аппаратные атомарные операции типа сравнения с заменой и т.п.
Если уж хочется работать с атомарными операциями - уж лучше пользоваться тем классом на мой взгляд чем хаками. )
Вы правы. Но тем не менее Sun связали и задокументировали.
http://download.oracle.com/javase/tutorial/essential/concurrency/atomic.html
Reads and writes are atomic for reference variables and for most primitive variables (all types except long and double).
Reads and writes are atomic for all variables declared volatile (including long and double variables).
public class Atomicity extends Thread {
volatile static int i=0;
boolean b;
Atomicity(boolean b) {
this.b = b;
}
public void run() {
if(b) i++;
System.out.println(i);
}
public static void main(String[] args) {
new Atomicity(true).start();
System.gc();
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
new Atomicity(false).start();
}
}
Выводит 1 1
Для начала нужно понимать, что сборщик мусора не собирает int'ы ;) ЕМНИП объект потока связан с потоком, который выполняется, так что ссылка на него продолжает существовать.
Ну и что, что статическая? Мне не понятно следующее: создается экземпляр Atomacity, значение i = 0, изменяем его на 1, убиваем этот экземпляр, создаем новый - По идее у него i должно равняться 0 но оно равняется 1