powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Java [игнор отключен] [закрыт для гостей] / Concurrency Vs multithreading
130 сообщений из 130, показаны все 6 страниц
Concurrency Vs multithreading
    #38614043
redwhite90
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Понятно, что Concurrency Vs multithreading это где-то рядом, но может всё таки есть какие-то отличия.
...
Рейтинг: 0 / 0
Concurrency Vs multithreading
    #38614083
забыл ник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Если в двух словах, multithreading - это выполнение задачи в нескольких потоках в целом, это скорее как парадигма. Concurrency не может существовать без multithreading - и в нем рассматриваются вопросы по взаимодействию потоков в том числе гарантии видимости, целостности, корректности. Concurrency - это когда есть работа в нескольких потоках с одними и теми же данными.
...
Рейтинг: 0 / 0
Concurrency Vs multithreading
    #38614085
For All
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Как по мне оба этих термина про одно и тоже
...
Рейтинг: 0 / 0
Concurrency Vs multithreading
    #38614156
redwhite90
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
забыл ник,

то есть когда я пишу thread.start() я думаю в основном о multithreading, а когда о wait/notify, то о concurrency ?
...
Рейтинг: 0 / 0
Concurrency Vs multithreading
    #38614178
забыл ник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
redwhite90забыл ник,

то есть когда я пишу thread.start() я думаю в основном о multithreading, а когда о wait/notify, то о concurrency ?

не совсем, multithreading он же возможен и на одном ядре. Это способ разбить задачу на юниты, которые могут, но не обязаны выполняться параллельно.
Concurrency же рассматривает как раз вопросы параллельного выполнения, и возникающие в связи с этим сложности, видимость, целостность, и тд
...
Рейтинг: 0 / 0
Concurrency Vs multithreading
    #38614237
redwhite90
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
забыл ник,

redwhite90то есть когда я пишу thread.start() я думаю в основном о multithreading

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

а где противоречие?
...
Рейтинг: 0 / 0
Concurrency Vs multithreading
    #38614329
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Мыши против сыра. Рок против наркотиков.
...
Рейтинг: 0 / 0
Concurrency Vs multithreading
    #38614717
DEVcoach
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
забыл никне совсем, multithreading он же возможен и на одном ядре. Это способ разбить задачу на юниты, которые могут, но не обязаны выполняться параллельно.
Concurrency же рассматривает как раз вопросы параллельного выполнения, и возникающие в связи с этим сложности, видимость, целостность, и тдНу видимость не гарантирована и на одноядерном процессоре. Отличие одноядерного процессора от многоядерного заключается в том, что не надо парится о когерентности кэшей. Но все остальное остается на своих местах - кэширование в регистрах, out-of-order execution, и т.д..
...
Рейтинг: 0 / 0
Concurrency Vs multithreading
    #38615089
redwhite90
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
DEVcoach,

я из без таких выражений, как "когерентности кэшей" верю, что ты разбираешься в этой теме)

но можно ж как-то почеловечнее выражаться)
...
Рейтинг: 0 / 0
Concurrency Vs multithreading
    #38615180
no56892
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
DEVcoachзабыл никне совсем, multithreading он же возможен и на одном ядре. Это способ разбить задачу на юниты, которые могут, но не обязаны выполняться параллельно.
Concurrency же рассматривает как раз вопросы параллельного выполнения, и возникающие в связи с этим сложности, видимость, целостность, и тдНу видимость не гарантирована и на одноядерном процессоре. Отличие одноядерного процессора от многоядерного заключается в том, что не надо парится о когерентности кэшей. Но все остальное остается на своих местах - кэширование в регистрах, out-of-order execution, и т.д..
DEVcoach, А как Вы "паритесь с когерентностью кэшэй" и что такое кэширование в регистрах?
...
Рейтинг: 0 / 0
Concurrency Vs multithreading
    #38615210
no56892
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
забыл никredwhite90забыл ник,

то есть когда я пишу thread.start() я думаю в основном о multithreading, а когда о wait/notify, то о concurrency ?

не совсем, multithreading он же возможен и на одном ядре. Это способ разбить задачу на юниты, которые могут, но не обязаны выполняться параллельно.
Concurrency же рассматривает как раз вопросы параллельного выполнения, и возникающие в связи с этим сложности, видимость, целостность, и тд
concurrency напрямую не зависит от количества ядер, а оно имеет место, когда 2+ потока обращаются к один и тем же данным (ресурсам).
...
Рейтинг: 0 / 0
Concurrency Vs multithreading
    #38615389
DEVcoach
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
no56892DEVcoach, А как Вы "паритесь с когерентностью кэшэй"Так же, как и остальные - через acquire/release :-)

no56892и что такое кэширование в регистрах?Оптимизации JITa. Сделайте следующее:

Код: java
1.
2.
3.
4.
5.
6.
7.
String s = null;

// Thread 1
while (s == null) {
    // Spin.
}
sout(s);


Через некоторое время (напр. через секунду) из другого потока:
Код: java
1.
2.
// Thread 2
s = "not null";


Thread 1 у вас не остановится. Потому что он уже не читает эту переменную ни из памяти, ни из кэша.
...
Рейтинг: 0 / 0
Concurrency Vs multithreading
    #38615425
no56892
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
DEVcoachno56892DEVcoach, А как Вы "паритесь с когерентностью кэшэй"Так же, как и остальные - через acquire/release :-)


no56892и что такое кэширование в регистрах?Оптимизации JITa. Сделайте следующее:

Код: java
1.
2.
3.
4.
5.
6.
7.
String s = null;

// Thread 1
while (s == null) {
    // Spin.
}
sout(s);


Через некоторое время (напр. через секунду) из другого потока:
Код: java
1.
2.
// Thread 2
s = "not null";


Thread 1 у вас не остановится. Потому что он уже не читает эту переменную ни из памяти, ни из кэша.

Вы шутите что-ли? : )
...
Рейтинг: 0 / 0
Concurrency Vs multithreading
    #38615461
DEVcoach
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
no56892Вы шутите что-ли? : )В чем именно?
...
Рейтинг: 0 / 0
Concurrency Vs multithreading
    #38615471
забыл ник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
no56892concurrency напрямую не зависит от количества ядер, а оно имеет место, когда 2+ потока обращаются к один и тем же данным (ресурсам).

Молодец, сразу видно что прочитал первый ответ в этой теме
...
Рейтинг: 0 / 0
Concurrency Vs multithreading
    #38615526
no56892
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
DEVcoachno56892Вы шутите что-ли? : )В чем именно?
Ну в том, что Ваш пример работает как и надо, т.е. полностью противоположно тому, что Вы написали. И, если есть, можно еще парочку примеров по управлению кэшем процессора из джавы.


авторМолодец, сразу видно что прочитал первый ответ в этой теме
Пропустил. Но, кстати в 4м Вашем же ответе все-таки уже не так однозначно как в первом, даже наоборот...
...
Рейтинг: 0 / 0
Concurrency Vs multithreading
    #38615549
DEVcoach
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
no56892Ну в том, что Ваш пример работает как и надо, т.е. полностью противоположно тому, что Вы написали. И, если есть, можно еще парочку примеров по управлению кэшем процессора из джавы.Ну вы бы меньше упражнялись в умении язвить, а больше писали по сути :-) Кэшами из Java не управляют. Из Java управляют видимостью изменений, используя acquire/release семантику. А эта семантика, в свою очередь:
1) Накладывает ограничения на оптимизации JIT.
2) Порождает барьеры памяти, которые приводят к синхронизации кэшей по определнным правилам. Это и есть, как вы выразились "управление кэшами из Java".

Ну а про пример кода, запустите вот это:
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
public class Runner {
    private static String s;

    public static void main(String[] args) throws Exception {
        new Thread(new Runnable() {
            @Override public void run() {
                while (s == null) {
                    // No-op.
                }

                System.out.println("2: String change observed: " + s);
            }
        }).start();

        Thread.sleep(1000);

        s = "str";

        System.out.println("1: String changed.");
    }
}

И скажите, остановилась ли у вас программа самостоятельно, или нет. Как минимум пользователи Windows дадут вам отрицательный ответ.
...
Рейтинг: 0 / 0
Concurrency Vs multithreading
    #38615601
Basil A. Sidorov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
В данном случае - "проделки JIT", если чуть изменить цикл, то всё работает:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
public class Runner {
    private static String s;

    public static void main(String[] args) throws Exception {
        new Thread(new Runnable() {
            @Override public void run() {
                while (s == null) {
                    Thread.currentThread().yield(); // disable loop unrolling, as I understand
                }

                System.out.println("2: String change observed: " + s);
            }
        }).start();

        Thread.sleep(1000);

        s = "str";

        System.out.println("1: String changed.");
    }
}
...
Рейтинг: 0 / 0
Concurrency Vs multithreading
    #38615605
Basil A. Sidorov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Basil A. SidorovВ данном случае - "проделки JIT оптимизатора"
...
Рейтинг: 0 / 0
Concurrency Vs multithreading
    #38615613
Basil A. Sidorov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Basil A. Sidorov// disable loop unrolling transformation to while(true);Что-то плохо соображаю.
...
Рейтинг: 0 / 0
Concurrency Vs multithreading
    #38615624
DEVcoach
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Basil A. SidorovВ данном случае - "проделки JIT", если чуть изменить цикл, то всё работаетнемножко усложним код:
Код: 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.
74.
75.
76.
import sun.misc.*;

import java.lang.reflect.*;
import java.security.*;

public class Runner {
    private static int s;

    private static int s0;

    private static int control;

    private static final Unsafe UNSAFE;

    private static final Object BASE;
    private static final long OFFSET;

    static {
        UNSAFE = unsafe();

        try {
            BASE = UNSAFE.staticFieldBase(Runner.class.getDeclaredField("s"));
            OFFSET = UNSAFE.staticFieldOffset(Runner.class.getDeclaredField("s"));
        }
        catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public static void main(String[] args) throws Exception {
        new Thread(new Runnable() {
            @Override public void run() {
                while (s == 0) {
                    s0 = UNSAFE.getInt(BASE, OFFSET);

                    control++;
                }

                System.out.println("2: change observed: " + s);
            }
        }).start();

        Thread.sleep(1000);

        s = 1;

        System.out.println("1: changed.");

        while (true) {
            Thread.sleep(1000);

            System.out.println("1: What 2 saw through Unsafe: " + s0);
            System.out.println("1: Control: " + control);
        }
    }

    public static Unsafe unsafe() {
        try {
            return Unsafe.getUnsafe();
        } catch (SecurityException ignored) {
            try {
                return AccessController.doPrivileged
                    (new PrivilegedExceptionAction<Unsafe>() {
                        @Override
                        public Unsafe run() throws Exception {
                            Field f = Unsafe.class.getDeclaredField("theUnsafe");
                            f.setAccessible(true);
                            return (Unsafe) f.get(null);
                        }
                    });
            } catch (PrivilegedActionException e) {
                throw new RuntimeException("Cannot get Unsafe.");
            }
        }
    }
}


Из него мы видим, что цикл никуда не делся, так как control постоянно изменяется. Однако изменения мы не видим даже через Unsafe.
...
Рейтинг: 0 / 0
Concurrency Vs multithreading
    #38615633
DEVcoach
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Basil A. SidorovЧто-то плохо соображаю.Контрольное чтение через Unsafe в s0 показывает, что поток не видит изменения значения, независимо от того, что там с условием цикла.
...
Рейтинг: 0 / 0
Concurrency Vs multithreading
    #38615645
Basil A. Sidorov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вот, что yield животворящий делает:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
>for /l %A in (0 1 4) do @java Runner
1: String changed.
2: String change observed: str
3: Control is: 9610699
1: String changed.
2: String change observed: str
3: Control is: 9759170
1: String changed.
2: String change observed: str
3: Control is: 9740589
1: String changed.
2: String change observed: str
3: Control is: 9606518
1: String changed.
2: String change observed: str
3: Control is: 9703600

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
public class Runner {
    private static String s;
    private static int control;

    public static void main(String[] args) throws Exception {
        new Thread(new Runnable() {
            @Override public void run() {
                while (s == null) {
                    Thread.currentThread().yield();
                    control++;
                }

                System.out.println("2: String change observed: " + s);
                System.out.println("3: Control is: " + control);
            }
        }).start();

        Thread.sleep(1000);

        s = "str";

        System.out.println("1: String changed.");
    }
}

...
Рейтинг: 0 / 0
Concurrency Vs multithreading
    #38615655
Basil A. Sidorov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Я бы сказал, что махинации с многопоточностью опасны не только из-за неопределённостью с процами, но и зависимостью от планировщиков операционных систем.
Так что - ну их нах.
...
Рейтинг: 0 / 0
Concurrency Vs multithreading
    #38615677
no56892
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
DEVcoachBasil A. SidorovЧто-то плохо соображаю.Контрольное чтение через Unsafe в s0 показывает, что поток не видит изменения значения, ...
Та ну?

Код: 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.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
import sun.misc.*;

import java.lang.reflect.*;
import java.security.*;

public class Go {
    private static int s;

    private static int s0;

    private static int control;

    private static final Unsafe UNSAFE;

    private static final Object BASE;
    private static final long OFFSET;

    static {
        UNSAFE = unsafe();

        try {
            BASE = UNSAFE.staticFieldBase(Go.class.getDeclaredField("s"));
            OFFSET = UNSAFE.staticFieldOffset(Go.class.getDeclaredField("s"));
        }
        catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public static void main(String[] args) throws Exception {
        new Thread(new Runnable() {
            @Override public void run() {
                while (s == 0) {
                		try {
											Thread.sleep(1);
										} catch (InterruptedException e) {
											// TODO Auto-generated catch block
											e.printStackTrace();
										}
										
                    s0 = UNSAFE.getInt(BASE, OFFSET);

                    control++;
                }

                System.out.println("2: change observed: " + s);
            }
        }).start();

        Thread.sleep(1000);

        s = 1;

        System.out.println("1: changed.");

        while (true) {
            Thread.sleep(1000);

            System.out.println("1: What 2 saw through Unsafe: " + s0);
            System.out.println("1: Control: " + control);
        }
    }

    public static Unsafe unsafe() {
        try {
            return Unsafe.getUnsafe();
        } catch (SecurityException ignored) {
            try {
                return AccessController.doPrivileged
                    (new PrivilegedExceptionAction<Unsafe>() {
                        @Override
                        public Unsafe run() throws Exception {
                            Field f = Unsafe.class.getDeclaredField("theUnsafe");
                            f.setAccessible(true);
                            return (Unsafe) f.get(null);
                        }
                    });
            } catch (PrivilegedActionException e) {
                throw new RuntimeException("Cannot get Unsafe.");
            }
        }
    }
}



PS. А зачем делать бесконечные циклы без sleep(1)? У вас же загрука ЦП 100% тогда
...
Рейтинг: 0 / 0
Concurrency Vs multithreading
    #38615686
Basil A. Sidorov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
no56892PS. А зачем делать бесконечные циклы без sleep(1)? У вас же загрука ЦП 100% тогдаА зачем замедлять работу программы?
Дали шанс выполниться другим потокам - и ладушки.
...
Рейтинг: 0 / 0
Concurrency Vs multithreading
    #38615687
DEVcoach
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
no56892 ,
Вы сути не уловили. Цикл здесь стоит для того, что бы показать, что второй поток не видит изменений первого неограниченно долгое время. Как вы можете объяснить причину этого? Почему я читаю переменную вновь и вновь, но не вижу в ней 1?
...
Рейтинг: 0 / 0
Concurrency Vs multithreading
    #38615695
0FD
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
DEVcoachBasil A. SidorovЧто-то плохо соображаю.Контрольное чтение через Unsafe в s0 показывает, что поток не видит изменения значения, независимо от того, что там с условием цикла.

Теперь осталось обьяснить почему изменения control в одном потоке видны в другом, a s нет, даже есть поставить s++ во второй цикл, ведь s и control ничем не отличаются, за исключением s в условии цикла.
...
Рейтинг: 0 / 0
Concurrency Vs multithreading
    #38615722
Basil A. Sidorov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Чуть модифицировал:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
public class Runner {
    private static String s;
    private static int control;

    public static void main(String[] args) throws Exception {
        new Thread(new Runnable() {
            @Override public void run() {
                while (s == null) {
                    control++;
                    Thread.currentThread().yield();
                }
                System.out.println("2: Change observed, control is: " + control);
            }
        }).start();

        Thread.sleep(1000);
        s = "str";
        System.out.println("1: String changed,  control is: " + control);
    }
}

Изменение видны сразу:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
>for /l %A in (0 1 4) do @java -Xshare:on Runner
1: String changed,  control is: 9349279
2: Change observed, control is: 9349279
1: String changed,  control is: 9361458
2: Change observed, control is: 9361458
1: String changed,  control is: 9450036
2: Change observed, control is: 9450036
2: Change observed, control is: 9367876
1: String changed,  control is: 9367876
1: String changed,  control is: 9401678
2: Change observed, control is: 9401678
...
Рейтинг: 0 / 0
Concurrency Vs multithreading
    #38616113
mesier
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ну, давайте я попробую объяснить! Мне ж ещё по собеседованиям ходить.. )))
Multithreading - параллельное, или псевдопараллельное (если всего один процессор) выполнение разного или одинакового кода в потоках операционной системы. Потоки отличаются от процессов тем, что выполняются в пределах одного адресного пространства памяти, выделенного на процесс.
Concurrency - один из способов синхронизации работы потоков, для согласования работы с общими данными, к которым обращается код из потоков. Вообще, весь этот способ стал актуальным с появлением многопроцессорных машин, а возможен стал благодаря появлению, сначала на RISC-овых процессорах, затем на x86 (кажется начиная с 586, или иначе "пентиум"), команды процессора casa и cmpxchg соответственно - или иначе CAS (compare-and-swap). Это атомарная операция. Атомарность гарантируется тем, что после считывания данных из ячейки памяти не освобождается шина данных, а сначала происходит сравнение, изменилось ли содержимое ячейки памяти.
Другой способ обеспечить эксклюзивный доступ к общей памяти - synchronizing - основан на использовании мьютексов операционной системы, и заключается фактически к установке последовательного, поочередного выполнения участков синхронизированного кода. Когда код входит в синхронизированный блок кода, он проверяет мьютекс, и если он установлен, то ждет освобождения.
На "несильно параллельных" многопоточных приложениях можно обеспечить эксклюзивный доступ к данным, и избежать ситуаций гонки, с помощью объявления совместно используемых переменных с ключевым словом volatile - в ряде случаев этого может оказаться достаточно. Часто используется совместно с синхронизацией. Объявление переменной с ключевым словом volatile гарантирует, что при модификации данных, значение будет записываться непосредственно в память, а не в кэш.
Вот вкратце..
Вопросы? )))
...
Рейтинг: 0 / 0
Concurrency Vs multithreading
    #38616121
DEVcoach
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
mesier ,
Откровенно говоря, буквально каждое предложение неверно :-) Попозже отвечу, когда время будет.
...
Рейтинг: 0 / 0
Concurrency Vs multithreading
    #38616137
mesier
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
DEVcoach, ой ли?
Может это вы неправильно понимаете что-то? )))
...
Рейтинг: 0 / 0
Concurrency Vs multithreading
    #38616165
DEVcoach
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
mesierMultithreading - параллельное, или псевдопараллельное (если всего один процессор) выполнение разного или одинакового кода в потоках операционной системы. Потоки отличаются от процессов тем, что выполняются в пределах одного адресного пространства памяти, выделенного на процесс.Да.
mesierConcurrency - один из способов синхронизации работы потоков, для согласования работы с общими данными, к которым обращается код из потоков.Нет. Канкарренси - это общение потоков в целом. Она не предполагает обязательную согласованность данных. Например, вы можете встретить намеренную несогласованность данных (data races) в классах java.util.concurrent (AbstractQueuedSynchronizer, ConcurrentHashMap, etc.). Но наличие этих несогласованностей не делает этот код "не конкурентным". Он еще какой конкурентный :-)

mesierВообще, весь этот способ стал актуальным с появлением многопроцессорных машинНет. Если говорить конкретно про проблемы согласованности данных, то они возникают и на однопроцессорных машинах благодаря оптимизациям JIT-компиляторов. Так что суди о актуальности этой проблемы по количеству процессоров - неверно.

mesierВообще, весь этот способ стал актуальным с появлением многопроцессорных машин, а возможен стал благодаря появлению, сначала на RISC-овых процессорах, затем на x86 (кажется начиная с 586, или иначе "пентиум"), команды процессора casa и cmpxchg соответственно - или иначе CAS (compare-and-swap). Это атомарная операция. Атомарность гарантируется тем, что после считывания данных из ячейки памяти не освобождается шина данных, а сначала происходит сравнение, изменилось ли содержимое ячейки памяти.Нет. Разграничивать работу кода можно и без атомарных операций. Например, см. алгоритм Петерсона, для его корректной работы на современных процессорах достаточно обычного volatile. Более того, не все арзитектуры имеют CAS в принципе. На некоторых реализован другой подход - LLSC, обладающий своими преимуществами. Например, отсутсвием ABA-проблемы. В любом случае, псиать конкурентных код можно и без CASов.

mesierДругой способ обеспечить эксклюзивный доступ к общей памяти - synchronizing - основан на использовании мьютексов операционной системы, и заключается фактически к установке последовательного, поочередного выполнения участков синхронизированного кода. Когда код входит в синхронизированный блок кода, он проверяет мьютекс, и если он установлен, то ждет освобождения.Если вы про ключевое слово synchornized, то неверно. Прежде, чем Java обратится к ОС за помощью она предпримет огромное количество действий, что бы этого избежать. Почитайте про thin и fat мониторы, и про biasing. Именно факт того, что в отсутствие contention synchronized не лезет в ОС делает его самым быстрым решением среди всех остальных других. А в присутствии contention он начинает проигрывать ReentrantLock.

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

mesierОбъявление переменной с ключевым словом volatile гарантирует, что при модификации данных, значение будет записываться непосредственно в память, а не в кэш.Нет, об этом я уже писал выше. volatile никак не влияет на расположение объектов в кэше. Кэшируется абсолютно все. volatile накладывет ограничение на то, какие оптимизации можно проводить с переменной. Например, как я уже писал выше, ее нельзя кэшировать в регистре. Нельзя игнорировать ее чтения. И т.д.. А JIT очень любит заниматься такой ерундой :-) Поэтому, volatile чтение медленнее обычного чтения не потому, что "переменной нет в кэше, и ее долго читать из памяти". Она есть в кэше. А потому, что JIT не имеет права применять к ней свои оптимизации.
...
Рейтинг: 0 / 0
Concurrency Vs multithreading
    #38616176
0FD
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
DEVcoach,

Тогда и про control и s обьясните, в чем отличие.
...
Рейтинг: 0 / 0
Concurrency Vs multithreading
    #38616196
mesier
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
DEVcoach, ну, теперь я вижу, что "на верхнем уровне абстракции" я всё-таки правильно рассказал. Вам просто до%%%ться захотелось.. ))
...
Рейтинг: 0 / 0
Concurrency Vs multithreading
    #38616199
DEVcoach
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
0FDТогда и про control и s обьясните, в чем отличие.Мой ответ такой - я не знаю, почему второй поток не видит s = 1 :-) Самый лучший способ достоверно это узнать - обратиться к Шипилеву/Куксенко/Иванову/Дагу.
...
Рейтинг: 0 / 0
Concurrency Vs multithreading
    #38616202
DEVcoach
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
mesierDEVcoach, ну, теперь я вижу, что "на верхнем уровне абстракции" я всё-таки правильно рассказал. Вам просто до%%%ться захотелось.. ))Ну если:
1) Сказать, что volatile не кэшируются, хотя они кэшируются;
2) Сказать, что volatile обеспечивает эксклюзивный доступ к данным, хотя она не делает этого;
3) Сказать, что конкарренси возможна только при наличии CAS, хотя это не так;
и т.д. это по-вашему "до@баться к мелочам", то пусть будет так :-)
...
Рейтинг: 0 / 0
Concurrency Vs multithreading
    #38616206
0FD
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
DEVcoach0FDТогда и про control и s обьясните, в чем отличие.Мой ответ такой - я не знаю, почему второй поток не видит s = 1 :-) Самый лучший способ достоверно это узнать - обратиться к Шипилеву/Куксенко/Иванову/Дагу.

Про s=1 понятно, я про control почему изменения control в одном потоке, видны другому, в отличии от s.
...
Рейтинг: 0 / 0
Concurrency Vs multithreading
    #38616234
mesier
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
DEVcoachmesierDEVcoach, ну, теперь я вижу, что "на верхнем уровне абстракции" я всё-таки правильно рассказал. Вам просто до%%%ться захотелось.. ))Ну если:
1) Сказать, что volatile не кэшируются, хотя они кэшируются;
2) Сказать, что volatile обеспечивает эксклюзивный доступ к данным, хотя она не делает этого;
3) Сказать, что конкарренси возможна только при наличии CAS, хотя это не так;
и т.д. это по-вашему "до@баться к мелочам", то пусть будет так :-)
Именно так, дои%%ться!. Я объяснил "на байтах" зачем нужен Concurrency, и очень кратко его основы, а не "только при наличии CAS". А вы ТСу хоть чем-нибудь помогли или только голову заморочили?
Кстати, ещё я не говорил слов "только" и "к мелочам", читайте, пожалуйста, внимательнее.
Человек вообще спросил о базовых понятиях.. А вы ему про Biased Locking.. ))) Разберётся, когда понадобится. Ибо "Я слышу, и забываю. Я вижу и запоминаю. Я делаю и понимаю", как-то так..
...
Рейтинг: 0 / 0
Concurrency Vs multithreading
    #38616283
забыл ник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
mesierDEVcoachпропущено...
Ну если:
1) Сказать, что volatile не кэшируются, хотя они кэшируются;
2) Сказать, что volatile обеспечивает эксклюзивный доступ к данным, хотя она не делает этого;
3) Сказать, что конкарренси возможна только при наличии CAS, хотя это не так;
и т.д. это по-вашему "до@баться к мелочам", то пусть будет так :-)
Именно так, дои%%ться!. Я объяснил "на байтах" зачем нужен Concurrency, и очень кратко его основы, а не "только при наличии CAS". А вы ТСу хоть чем-нибудь помогли или только голову заморочили?
Кстати, ещё я не говорил слов "только" и "к мелочам", читайте, пожалуйста, внимательнее.
Человек вообще спросил о базовых понятиях.. А вы ему про Biased Locking.. ))) Разберётся, когда понадобится. Ибо "Я слышу, и забываю. Я вижу и запоминаю. Я делаю и понимаю", как-то так..

В этот раз соглашусь со свеномом, многопоточность сложная тема, и именно в деталях и терминах кроется дьявол. Так как примногопоточном программировании ошибку допустить проще простого, как раз таки понимание этих деталей и рулит. Не буду утверждать что я сам гуру, но множество приведенных вами неточностей позволяет сделать вывод про уровень ваших знаний, да, я бы взял вас в команду писать код, который просто работает в разных потоках, но я бы не взял вас в команду по написанию чего-то нового и нешаблонного(пока что). Вообще многопоточность такая штука, в которой просто необходима практика, практика и еще раз практика, а лучше всего пяток пофикшенных гейзенбагов :)
...
Рейтинг: 0 / 0
Concurrency Vs multithreading
    #38616306
For All
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
mesierВообще, весь этот способ стал актуальным с появлением многопроцессорных машин, а возможен стал благодаря появлению, сначала на RISC-овых процессорах, затем на x86 (кажется начиная с 586, или иначе "пентиум"), команды процессора casa и cmpxchg соответственно - или иначе CAS (compare-and-swap).
Вообще-то мгопоточность программировали ещё на 8086 процессоре (даже не 80186 и тем более задолго до появления 80286). CAS-операций в 8086 как известно нет. Как же они делали это?
...
Рейтинг: 0 / 0
Concurrency Vs multithreading
    #38616307
DEVcoach
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
0FDПро s=1 понятно, я про control почему изменения control в одном потоке, видны другому, в отличии от s.x86 достаточно консервативна в возможных реордерингах на железном уровне: TSO. Поэтому по-хорошему за редким ислключением все должны видеть всех. Поэтому я склонен винить в "невидимости" s JIT, а не железо. Судя по всему, он не посчитал нужным записать новое значение s в память. Но это только догадка.
...
Рейтинг: 0 / 0
Concurrency Vs multithreading
    #38616314
0FD
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
DEVcoach,

Пришлось читать jls

Если добавить System.out.println :
Код: java
1.
2.
3.
4.
while (s==0) {
   s0 = UNSAFE.getInt(BASE, OFFSET);
   System.out.println("2111: change observed: " + s0+" "+s);
   control++;


читается s=1, цикл заканчивается
Получается System.out.println является Synchronization actions которое заставляет читать s=1, такое Synchronization actions заставляет читать counter в другом потоке. Первым Synchronization actions является Thread.start, и во второй поток считывается s=0
...
Рейтинг: 0 / 0
Concurrency Vs multithreading
    #38616326
For All
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
DEVcoachmesierНа "несильно параллельных" многопоточных приложениях можно обеспечить эксклюзивный доступ к данным, и избежать ситуаций гонки, с помощью объявления совместно используемых переменных с ключевым словом volatile - в ряде случаев этого может оказаться достаточно.Нет. volatile не обеспечивает эксклюизвный доступ к памяти. Она лишь обеспечивает видимость изменений между потоками с помощью барьеров памяти. Таким образом, volatile синхронизирует состояние памяти между потоками, но не синхронизирует порядок доступа к памяти этими потоками.
По-моему mesier имеет ввиду, что операция записи значения в volatile переменную гарантировано атомарная (например запись в не-volatile поле типа long не обязательно атомарна, т.е. возможна ситуация, что другой поток увидит наполовину старое/наполовину изменённое значение)
...
Рейтинг: 0 / 0
Concurrency Vs multithreading
    #38616332
забыл ник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
0FDПолучается System.out.println является Synchronization actions

Несогласен с формулировкой, просто JIT выключает свои оптимизации, потому что видит что считанная переменная используется далее.
...
Рейтинг: 0 / 0
Concurrency Vs multithreading
    #38616343
0FD
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
забыл ник0FDПолучается System.out.println является Synchronization actions

Несогласен с формулировкой, просто JIT выключает свои оптимизации, потому что видит что считанная переменная используется далее.

Да и без sysout , s используется далее
Код: java
1.
while (s==0)
...
Рейтинг: 0 / 0
Concurrency Vs multithreading
    #38616360
DEVcoach
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
0FDПолучается System.out.println является Synchronization actions которое заставляет читать s=1, такое Synchronization actions заставляет читать counter в другом потоке. Первым Synchronization actions является Thread.start, и во второй поток считывается s=0Нет. Вы сейчас пытаетесь объяснить это, основываясь на ваших знаниях работы Java. Но вы не учитываете то, что много чего еще не знаете.
Вернее, если быть точным, вы пытаетесь подогнять ваши знания под наблюдаемое поведение. Так лучше не делать. sout не является synchronization action. Но это как минимум системный вызов, который обращается к ядру операционки, порождает context switch, и т.д.. В процессе этой сложной последовательности действий каким-то образом данные между потоками всетаки синхронизируются. Но почему это происходит - большой вопрос. Поэтому нельзя сказать, что sout это synchronization action.
...
Рейтинг: 0 / 0
Concurrency Vs multithreading
    #38616384
0FD
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
DEVcoach0FDПолучается System.out.println является Synchronization actions которое заставляет читать s=1, такое Synchronization actions заставляет читать counter в другом потоке. Первым Synchronization actions является Thread.start, и во второй поток считывается s=0Нет. Вы сейчас пытаетесь объяснить это, основываясь на ваших знаниях работы Java. Но вы не учитываете то, что много чего еще не знаете.
Вернее, если быть точным, вы пытаетесь подогнять ваши знания под наблюдаемое поведение. Так лучше не делать. sout не является synchronization action. Но это как минимум системный вызов, который обращается к ядру операционки, порождает context switch, и т.д.. В процессе этой сложной последовательности действий каким-то образом данные между потоками всетаки синхронизируются. Но почему это происходит - большой вопрос. Поэтому нельзя сказать, что sout это synchronization action.

Это Вы хорошо написали о моих знаниях и наблюдениях. Посмотрите PrintStream.println(тот же sysout)
Код: java
1.
2.
3.
4.
5.
6.
public void println(String x) {
        synchronized (this) {
            print(x);
            newLine();
        }
}


и jls 17.4.2 Actions
Synchronization actions, which are:
Volatile read. A volatile read of a variable.
Volatile write. A volatile write of a variable.
Lock. Locking a monitor <-------------------------------
Unlock. Unlocking a monitor.
The (synthetic) first and last action of a thread
Actions that start a thread or detect that a thread has terminated, as described in §17.4.4.

и после этого System.out.println не Synchronization actions?
...
Рейтинг: 0 / 0
Concurrency Vs multithreading
    #38616562
DEVcoach
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
0FD ,

Вы меня неправильно поняли :-) Под "много чего не знаете", я имел ввиду в первую очередь внутреннее устройство операционки, железа, и прочих низкоуровневых вещей. Говоря "вы много чего не знаете", я не претендую на то, что я это знаю. Вы привели в пример sout, и смогли найти этому объяснение. Отлично. Но во-первых, это не полное объяснение, т.к. с точки зрения JMM в этом случае есть acquire в читающем потоке, но нет release в пишущем.
Во-вторых, есть масса других способ заставить этот поток увидеть s=1. Например, как уже приводили выше пример, с помощью Thread.yield(). Как вы объясните, что видимость появляется в этом случае? Это нативный метод, к synchronization action не относится ... а видимость дает?
Наконец, к synchronization action относят только то, что указано в JMM, базовые кирпичики. Все, что свыше - это не новые sync actions, а лишь надстройки над имеющимися.
...
Рейтинг: 0 / 0
Concurrency Vs multithreading
    #38616581
no56892
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
DEVcoach ,
Кстати, Вы выдвигали версию о том, что это можно объяснить якобы "кэширванием в регистрах", дак вот, попробуйте затестить Ваш же пример с 17 переменными (целочисленных регистров AMD64 - 16).
...
Рейтинг: 0 / 0
Concurrency Vs multithreading
    #38616590
DEVcoach
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
no56892 DEVcoach ,
Кстати, Вы выдвигали версию о том, что это можно объяснить якобы "кэширванием в регистрах", дак вот, попробуйте затестить Ваш же пример с 17 переменными (целочисленных регистров AMD64 - 16).Ну напишите :-) А смысл этих мытарств в чем? Может это регистры, может JIT закэшировал значение в стэке, и не трогает хип. Может быть еще что-то. Прикладной ценности эти копания не имеют.
...
Рейтинг: 0 / 0
Concurrency Vs multithreading
    #38616625
0FD
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
DEVcoachВо-вторых, есть масса других способ заставить этот поток увидеть s=1. Например, как уже приводили выше пример, с помощью Thread.yield(). Как вы объясните, что видимость появляется в этом случае? Это нативный метод, к synchronization action не относится ... а видимость дает?

Не только yield, но и со sleep. Хотя jls 17.9 Sleep and Yield
...
It is important to note that neither Thread.sleep nor Thread.yield have any synchronization semantics. In particular, the compiler does not have to flush writes cached in registers out to shared memory before a call to Thread.sleep or Thread.yield, nor does the compiler have to reload values cached in registers after a call to Thread.sleep or Thread.yield.
...
...
Рейтинг: 0 / 0
Concurrency Vs multithreading
    #38616862
Basil A. Sidorov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
For AllВообще-то мгопоточность программировали ещё на 8086 процессоре (даже не 80186 и тем более задолго до появления 80286). CAS-операций в 8086 как известно нет. Как же они делали это?Насколько я помню, префикс lock был изначально. Более следующие процессоры просто ограничили его использование.
Плюс, Intel изначально реализовала "блокировку прерываний" для команд, меняющих SP. Именно для того, чтобы гарантировать атомарное переключение стека.
...
Рейтинг: 0 / 0
Concurrency Vs multithreading
    #38616879
For All
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Basil A. SidorovFor AllВообще-то мгопоточность программировали ещё на 8086 процессоре (даже не 80186 и тем более задолго до появления 80286). CAS-операций в 8086 как известно нет. Как же они делали это?Насколько я помню, префикс lock был изначально. Более следующие процессоры просто ограничили его использование.
Плюс, Intel изначально реализовала "блокировку прерываний" для команд, меняющих SP. Именно для того, чтобы гарантировать атомарное переключение стека.
Насколько я помню, на 8086 многопоточность делали без использования "блокировки прерываний". Тем не менее работало.
...
Рейтинг: 0 / 0
Concurrency Vs multithreading
    #38616885
Basil A. Sidorov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
For AllНасколько я помню, на 8086 многопоточность делали без использования "блокировки прерываний"Это вы так думаете.
Системный таймер (мегагерц с копейками поделённый на 64к) мог тикнуть в любое времяТем не менее работало.Оно потому и работало, что национальные особенности записи в SP обеспечивали беспроблемное переключение стека, а lock гарантировал работу семафоров. Если, конечно, они использовались.
...
Рейтинг: 0 / 0
Concurrency Vs multithreading
    #38616958
mesier
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
забыл ник В этот раз соглашусь со свеномом, многопоточность сложная тема, и именно в деталях и терминах кроется дьявол. Так как примногопоточном программировании ошибку допустить проще простого, как раз таки понимание этих деталей и рулит. Не буду утверждать что я сам гуру, но множество приведенных вами неточностей позволяет сделать вывод про уровень ваших знаний, да, я бы взял вас в команду писать код, который просто работает в разных потоках, но я бы не взял вас в команду по написанию чего-то нового и нешаблонного(пока что). Вообще многопоточность такая штука, в которой просто необходима практика, практика и еще раз практика, а лучше всего пяток пофикшенных гейзенбагов :)
Именно так - практика! И как раз практики-то с многопоточностью у меня нет, и именно поэтому забылись детали теории (неиспользуемые знания забываются).
Таки куда приходить собеседоваться на позицию "писать код, который просто работает" ? )) Удалёнку рассматриваете?
Я как раз сейчас в поиске работы..
...
Рейтинг: 0 / 0
Concurrency Vs multithreading
    #38617341
For All
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Basil A. SidorovFor AllНасколько я помню, на 8086 многопоточность делали без использования "блокировки прерываний"Это вы так думаете.
Системный таймер (мегагерц с копейками поделённый на 64к) мог тикнуть в любое времяИ он тикал - прерывания же не блокировались. И клавиатура тикала по нажатию клавиши, и последовательные порты. Вообще все прерывания срабатывали.Basil A. SidorovТем не менее работало.Оно потому и работало, что национальные особенности записи в SP обеспечивали беспроблемное переключение стека, а lock гарантировал работу семафоров. Если, конечно, они использовались.lock - это блокировка шины на время выполнения команды, актуальна для многопроцессорных/многоядерных систем, и к реализации семафоров на процессоре 8086 (который не яляется многоядерным) не имеет никакого отношения.
...
Рейтинг: 0 / 0
Concurrency Vs multithreading
    #38617484
no56892
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
For AllBasil A. Sidorovпропущено...
Это вы так думаете.
Системный таймер (мегагерц с копейками поделённый на 64к) мог тикнуть в любое времяИ он тикал - прерывания же не блокировались. И клавиатура тикала по нажатию клавиши, и последовательные порты. Вообще все прерывания срабатывали.Basil A. Sidorovпропущено...
Оно потому и работало, что национальные особенности записи в SP обеспечивали беспроблемное переключение стека, а lock гарантировал работу семафоров. Если, конечно, они использовались.lock - это блокировка шины на время выполнения команды, актуальна для многопроцессорных/многоядерных систем, и к реализации семафоров на процессоре 8086 (который не яляется многоядерным) не имеет никакого отношения.
А что за lock? Разве одной команды? Я всегда думал, что именно чтобы несколько команд выполнить, так сказать транзакцию. А смысл что-то я непойму: на "электрическом уровне" тот-же "mov <something>, 0xadress" implicitly лочит шину или как?

А по поводу while(sharedobject.field == 0) { ... } я засабмитил баг в оракл, это ИМХО явный баг. Посмотрим результаты...
...
Рейтинг: 0 / 0
Concurrency Vs multithreading
    #38617500
For All
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
no56892А что за lock? Разве одной команды? Я всегда думал, что именно чтобы несколько команд выполнить, так сказать транзакцию. А смысл что-то я непойму: на "электрическом уровне" тот-же "mov <something>, 0xadress" implicitly лочит шину или как? lock - Assert LOCK# signal for the next instruction. The LOCK prefix causes the LOCK# signal to be asserted during execution of the instruction that follows it.
И ещё по поводу шины.
...
Рейтинг: 0 / 0
Concurrency Vs multithreading
    #38617516
no56892
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
For Allno56892А что за lock? Разве одной команды? Я всегда думал, что именно чтобы несколько команд выполнить, так сказать транзакцию. А смысл что-то я непойму: на "электрическом уровне" тот-же "mov <something>, 0xadress" implicitly лочит шину или как? lock - Assert LOCK# signal for the next instruction. The LOCK prefix causes the LOCK# signal to be asserted during execution of the instruction that follows it.
И ещё по поводу шины.
Это если одна шина на память и на IO устройства, а какой смысл в lock если сейчас в в процессоре как минимум одна шина на память и одна на IO ?
...
Рейтинг: 0 / 0
Concurrency Vs multithreading
    #38617534
For All
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
no56892А что за lock? Разве одной команды? Я всегда думал, что именно чтобы несколько команд выполнить, так сказать транзакцию. А смысл что-то я непойму: на "электрическом уровне" тот-же "mov <something>, 0xadress" implicitly лочит шину или как?no56892Это если одна шина на память и на IO устройства, а какой смысл в lock если сейчас в в процессоре как минимум одна шина на память и одна на IO ?
Например, команда add <something>, 0xadress с точки зрения шины не атомарна - там несколько общений к шине идёт. В многопроцессорной/многоядерной системе разные процессоры/ядра запросто могут обратиться в одну и ту же ячейку памяти (по одной и тоже шине на память) и поломать add друг-другу.
...
Рейтинг: 0 / 0
Concurrency Vs multithreading
    #38617600
no56892
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
For Allno56892А что за lock? Разве одной команды? Я всегда думал, что именно чтобы несколько команд выполнить, так сказать транзакцию. А смысл что-то я непойму: на "электрическом уровне" тот-же "mov <something>, 0xadress" implicitly лочит шину или как?no56892Это если одна шина на память и на IO устройства, а какой смысл в lock если сейчас в в процессоре как минимум одна шина на память и одна на IO ?
Например, команда add <something>, 0xadress с точки зрения шины не атомарна - там несколько общений к шине идёт. В многопроцессорной/многоядерной системе разные процессоры/ядра запросто могут обратиться в одну и ту же ячейку памяти (по одной и тоже шине на память) и поломать add друг-другу.
А, понял.
...
Рейтинг: 0 / 0
Concurrency Vs multithreading
    #38617807
Фотография k0rvin
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
забыл никне совсем, multithreading он же возможен и на одном ядре. Это способ разбить задачу на юниты, которые могут, но не обязаны выполняться параллельно.
Concurrency же рассматривает как раз вопросы параллельного выполнения, и возникающие в связи с этим сложности, видимость, целостность, и тд

В общем-то конкурентные программы могут работать в одном потоке, т.к. конкурентность часто обеспечивается "софтово" -- виртуальной машиной или рантаймом языка и не зависит от потоков/процессов ОС (но может их использовать).

Собственно вот.

Так что по сути разница между multithreading и concurrency только в реализации, а параллельные вычисления -- совсем другая тема.
...
Рейтинг: 0 / 0
Concurrency Vs multithreading
    #38617958
Basil A. Sidorov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
For Alllock - это блокировка шины на время выполнения команды, актуальна для многопроцессорных/многоядерных систем, и к реализации семафоров на процессоре 8086 (который не яляется многоядерным) не имеет никакого отношения.Мопвашуять ...
Вы постоянно игнорируете периферийное железо, которое сидело той же самой (общей) шине. Не процессором единым ...
...
Рейтинг: 0 / 0
Concurrency Vs multithreading
    #38686622
redwhite90
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
DEVcoach Сказать, что volatile не кэшируются, хотя они кэшируются;


Можно отсюда поподробнее ?

Что происходит в тот момент, когда я пытаюсь считать волатильную перменную ?
У меня в каждом потоке свое закешированное значение волатильной переменной(непосредственно перед чтением), как они синхронизируются? Как выбирается самое актуальное значение?

P.S. я знаю, что volatile write happens-before volatile read
...
Рейтинг: 0 / 0
Concurrency Vs multithreading
    #38686645
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
redwhite90Что происходит в тот момент, когда я пытаюсь считать волатильную перменную ?
У меня в каждом потоке свое закешированное значение волатильной переменной(непосредственно перед чтением), как они синхронизируются? Как выбирается самое актуальное значение?
P.S. я знаю, что volatile write happens-before volatile read
Грубо говоря на пальцах это так: переменная - это значение в памяти. Кэш это регистр процессора. Обычную переменную можно не читать из памяти (долго), а прочитать из регистра (быстро). Чтение volatile переменной происходит из памяти. Поэтому там актуальное значение, а не из регистра, где может быть устаревшее.
...
Рейтинг: 0 / 0
Concurrency Vs multithreading
    #38686658
redwhite90
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Blazkowicz,

спасибо.

Получается, что при каждом изменении волатильной переменной она записывается в локальный кеш потока и в память.

P.S. Значит всё-таки "суперкопия" существует.
...
Рейтинг: 0 / 0
Concurrency Vs multithreading
    #38686661
redwhite90
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Blazkowicz,

ну и возникает вопрос, зачем вообще тогда кэшировать волатильные переменные?
...
Рейтинг: 0 / 0
Concurrency Vs multithreading
    #38686671
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
redwhite90Blazkowicz,

ну и возникает вопрос, зачем вообще тогда кэшировать волатильные переменные?
Зависит от алгоритма. Можешь кешировать. И ты получишь ретроспективноее ее представление.
Твой алгоритм будет быстр - но синхронен с "точкой времени в прошлом". По аналогии с курсорами
версионных СУБД. Ты не получаешь объективные данные. А ты получаешь данные на момент когда
открылся курсор (у тебя - начался твой АЛГОРИТМ).

Короче это algorithm depends.
...
Рейтинг: 0 / 0
Concurrency Vs multithreading
    #38686692
redwhite90
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
maytonredwhite90Blazkowicz,

ну и возникает вопрос, зачем вообще тогда кэшировать волатильные переменные?
Зависит от алгоритма. Можешь кешировать. И ты получишь ретроспективноее ее представление.
Твой алгоритм будет быстр - но синхронен с "точкой времени в прошлом". По аналогии с курсорами
версионных СУБД. Ты не получаешь объективные данные. А ты получаешь данные на момент когда
открылся курсор (у тебя - начался твой АЛГОРИТМ).

Короче это algorithm depends.

в java я же не могу получить неактуальное значение волатильной переменой. И соответственно алгоритм свой написать не могу.
...
Рейтинг: 0 / 0
Concurrency Vs multithreading
    #38686695
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
redwhite90в java я же не могу получить неактуальное значение волатильной переменой. И соответственно алгоритм свой написать не могу.
Поэтому в Java, чтобы не изучать арихитектуру каждого CPU и особенности JIT компиляции под него, сделана единая JMM, на которую нужно ориентироваться.
...
Рейтинг: 0 / 0
Concurrency Vs multithreading
    #38686701
redwhite90
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Blazkowicz,

я наверное непонятно задаю вопрос.

Что поменялось бы если бы волатильная переменная не кешировалась бы? Есть хоть один кейс, когда используется значение волатильной переменной из кеша?
...
Рейтинг: 0 / 0
Concurrency Vs multithreading
    #38686705
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
redwhite90Что поменялось бы если бы волатильная переменная не кешировалась бы? Есть хоть один кейс, когда используется значение волатильной переменной из кеша?
С точки зрения Java - разницы никакой нет.
...
Рейтинг: 0 / 0
Concurrency Vs multithreading
    #38686706
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
redwhite90maytonпропущено...

Зависит от алгоритма. Можешь кешировать. И ты получишь ретроспективноее ее представление.
Твой алгоритм будет быстр - но синхронен с "точкой времени в прошлом". По аналогии с курсорами
версионных СУБД. Ты не получаешь объективные данные. А ты получаешь данные на момент когда
открылся курсор (у тебя - начался твой АЛГОРИТМ).

Короче это algorithm depends.

в java я же не могу получить неактуальное значение волатильной переменой. И соответственно алгоритм свой написать не могу.
Давай на конкретном случае. Если волатальная переменная - это статистический счётчик
который ты просто сыплешь в лог или кидаешь в интерфейсы мониторинга - это одно дело.

Если она - это аргумент алгоритма - то тебе придётся "сбрасывать" алгоритм и каждый раз
заново выполнять перерасчёт чтобы обеспечить актуальность. Отсюда вопрос. Зачем
вообще нужна эта "грязная" (dirty) волатальная перменная. Может лучше переписать код и организовать
events которые будут запускать другие потоки с актуальными аргументами?

Может с другой стороны подойти к синхронизации?

Может volatile это вовсе не тот философский камень который тебе нужен?
...
Рейтинг: 0 / 0
Concurrency Vs multithreading
    #38686728
Фотография Usman
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
redwhite90Что поменялось бы если бы волатильная переменная не кешировалась бы?Очевидно увеличится время получения значения из памяти
...
Рейтинг: 0 / 0
Concurrency Vs multithreading
    #38686736
redwhite90
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Usmanredwhite90Что поменялось бы если бы волатильная переменная не кешировалась бы?Очевидно увеличится время получения значения из памяти

Что-то для меня это вообще не очевидно.
...
Рейтинг: 0 / 0
Concurrency Vs multithreading
    #38686751
Фотография Usman
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
redwhite90Usmanпропущено...
Очевидно увеличится время получения значения из памятиЧто-то для меня это вообще не очевидно. http://ru.wikipedia.org/wiki/Кэш_процессора
...
Рейтинг: 0 / 0
Concurrency Vs multithreading
    #38686753
redwhite90
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Usman,

мы ж уже разобрались, что волатильная перменная один хрен будет читаться из памяти. Получается наоборот имеем излишние накладные расходы на запись в кеш, из которого никогда не будем читать эту переменную.
...
Рейтинг: 0 / 0
Concurrency Vs multithreading
    #38686763
Фотография Usman
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
redwhite90Что поменялось бы если бы волатильная переменная не кешировалась бы? 16254221 redwhite90волатильная перменная один хрен будет читаться из памятиС этим никто не спорит, другое дело, операция чтения/записи в volatile-переменную будет медленнее.
...
Рейтинг: 0 / 0
Concurrency Vs multithreading
    #38686772
redwhite90
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Usmanredwhite90Что поменялось бы если бы волатильная переменная не кешировалась бы? 16254221 redwhite90волатильная перменная один хрен будет читаться из памятиС этим никто не спорит, другое дело, операция чтения/записи в volatile-переменную будет медленнее.

Поясните!

В одном случае пишется только в память, в другом в память и в кеш. и вы утверждаете, что писать в память и в кеш быстрее нежели чем просто в кеш.
...
Рейтинг: 0 / 0
Concurrency Vs multithreading
    #38686848
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
redwhite90, volatile будет медленнее.
...
Рейтинг: 0 / 0
Concurrency Vs multithreading
    #38686937
redwhite90
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
maytonredwhite90, volatile будет медленнее.
согласен, но как это коррелируется с


Usmanredwhite90Что поменялось бы если бы волатильная переменная не кешировалась бы?
Очевидно увеличится время получения значения из памяти

вообще не понимаю как это связано.


UsmanС этим никто не спорит, другое дело, операция чтения/записи в volatile-переменную будет медленнее.
медленне в каком случае ?как сейчас, когда пишется и в кеш и в память или когда пишется только в память?


и кстати Blazkowicz , что подразумевается под памятью?
...
Рейтинг: 0 / 0
Concurrency Vs multithreading
    #38686943
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
redwhite90и кстати Blazkowicz , что подразумевается под памятью?
Современные процессоры, намного сложнее устроены. То что я тебе описал, это примерно на уровне Z80 и 8086.
...
Рейтинг: 0 / 0
Concurrency Vs multithreading
    #38687357
DEVcoach
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
redwhite90 ,
Вынужден констатировать, что все предоставленные вам ответы либо вообще некорректны, либо используют некорректную терминологию, а от того еще больше запутывают. Для понимания работы volatile (и JMM в целом) недостаточно знать Java. Надо понимать архитектуру компьютеру. Постараюсь вам все пояснить, пройдя "снизу вверх".

I.
Давайте начнем с того, что представим себе, что процессор общается с памятью напрямую. То есть нет никаких регистров, нет никаких кэшей, есть только ядро, память, и шина (суть "провода"), связывающие память и процессор.
Когда процессору надо запросить какую-то информацию, он просто говорит памяти "дай мне данные по адресу 100".
Просто? Просто.

II.
К сожалению, упомянутый выше подход не работает. Что такое код программы? Что записано в exe файле, в dll'ке или so'шнике? Это набор инструкций, которые процессор исполняет. В общем случае инструкции выполняются последовательно. Но иногда необходимо перепрыгнуть ряд инструкций, и уйти в другую область кода. Например, когда вы встретили if. Для этого у каждого процессора есть набор соответствующих инструкций (jmp, jne, и т.д..). Но для того, что бы осуществить прыжок, нужно знать адрес той инструкции, на которую надо прыгнуть. Отсюда мы приходим, что каждая инструкция должна иметь адрес, что бы можно было на нее "прыгнуть", так?
Окей. а как задать адреса инструкциям? Как записать эти адреса в exe файл? Ну давайте просто последовательно их выдавать, начиная с нуля: 0, 1, 2, 3, ... А потом, когда мы запустим exe-шник, он просто загрузит эти инструкции в память по этим же адресам. То есть инструкция с адресом 100 будет в ячейке памяти 100, 101 в 101, и т.д..
Круто? Не очень, Ведь если вы сначала загрузили программу A, которая заняла адреса 0 ... 100, дошли до инструкции 50, а там вам сказали прыгнуть на 80. А в это время вы запустили программу B, которая перетерла эти инструкции своим кодом. В итоге вы из программы A прыгните на инструкцию 80 ... и начнете выполнять другую программу. Это не круто.
Аналогично и с данными, которые нужны программе. Допустим, вы хотите записать по константному адресу какое-то значение, что бы другие участки программы могли ее считать. Вы говорите "запиши эту стрингу по адресу 100500". Потому стартует другая программа, которая ничего не знает о вашей, и просто перетирает ваши данные. Не круто.

III.
Что бы забороть эти проблемы вводят понятие виртуальных адресов. Когда вы стартуете процесс, ОС выделяет ему какую-то область памяти, к которой имеет доступ он и только он. Например, приложению A дали адреса 0 ... 99, приложению B 100 ... 199. Это круто. Но ведь в exe-шниках обеих программ записаны адреса, начиная с нуля! Как быть? А так, что процессор начинает работать с теми адресами, что записаны в исполняемом файле. Это виртуальные адреса. Но он каким-то образом понимает, что виртуальный адрес 10 для конкретного процесса, это адрес 110 в "реальной памяти" (физический адрес).
Отсюда мы приходим к тому, что процессор не может работать с памятью напрямую. Ему как минимум нужен преобразователь адресов.
Назовем это устройство "контроллер памяти". Он находится где-то между процессором и физической планкой памяти. И процессор вообще ничего не знает о памяти, установленной внутри вашей системы. Он знает только протокол общения с этим контроллером, и все.

IV.
Мы знаем, что адреса всегда проходят через этот контроллер. И каждый раз мы получаем виртуальный адрес, каким-то образом превращаем его в физический адрес, и отправляем запрос в память. Потом получаем ответ, делаем обратное преобразование, и отвечаем процессору. А можно ли как-то закэшировать эти пары? Ну, например, если я однажды узнал, что виртуальный адрес 100, а это реальный адрес 995, то я бы хотел запомнить где-то пару (100, 995), что бы потом быстрее делать эти преобразования. Это реально? Конечно реально! Для этого почти на каждом современном процессоре есть так называемый translation lookaside buffer (TLB), который хранит эти пары, ускоряя преобразования виртуаьлных адресов в физические и наоборот. Процессор ничего не знает про этот кэш, он просто спрашивает контроллер.

V.
Мы так же знаем, что данные так же всегда проходят через этот контроллер, так как процессор не может работать с памятью напрямую. Можем ли мы кэшировать данные так же, как мы кэшируем пары (виртуальный адрес, физический адрес)? Конечно можно! Давайте просто будем сохранять все прошедшие через нас данные куда-то, тем самым ускоряя доступ к ним? Это будет немного медленнее, чем прямая запись в память при первой записи/чтении, но даст нам огромный прирост при последующих доступах к этому же адресу.
Мы приходим к первому важному выводу: процессор ничего не знает про кэш. Ни-че-го. Он не может сказать "дайте мне вот это из кэша, а вот это из физической планки". Он просто говорит контроллеру "дай мне такой-то адрес" или "запиши по такому-то адресу", а контроллер уже сам решает, как ему поступить.
ВЫВОД 1: Процессор не отличает память и кэш, для него это единая комплексная система.

VI.
Когда у нас появляется больше, чем одно ядро, мы выделяем каждому ядру по своему кэшу. Но возникает вопрос: а что будет, если два ядра одновременно будут читать/писать по одному адресу? Будут проблемы. Например, в кэше одного процессора может оказаться одно значение, а в кэше другого другое. Или вот другая проблема - что, если в кэше нашего процессора нет значения адреса 100, но он есть в кэше другого процессра? Что нам делать - бежать в основную память, или запросить значение в другом кэше? Быстрее будет запросить у другого кэша.
Поэтому, что бы скоординировать действия кэшей разных процессоров, нам надо придумать какой-то протокол их взаимодействия, надо придумать протокол когерентности кэшей . И он был придуман - MESI, и его многочисленные вариации. Когда один процессор записывает что-то по адресу A, то подсистема памяти проверяет кэши всех процессоров, что бы убедиться, что они сотрут (инвалидируют) у себя старое значение, и на следующем чтении смогут вычитать новое значение.
Проблема в том, что протоколы когерентности привносят накладные расходы, которые хотелось бы минимизировать. И были придуманы две хитрости:
1) Когда мы делаем запись, то надо сначала инвалидировать значения в других кэшах, а потом уж записать свое значение. Окей, мы запускаем этот процесс ... но не ждем его завершения, а тут же сообщаем процессору "да, все ничтяк, записал", и идем дальше. И пока этот процесс не завершился, новое значение хранится в специальной структуре конкретного ядра - store buffer. Если процессору потребуется еще раз это значение, то мы выдадим ему значение из store buffer. А потом, чуть позже, когда другие кэши ответят, что успешно инвалидировали старое значение, мы уже по-настоящему перенесем это значение из store buffer в кэш.
2) Когда наш кэш просят инвалидировать значение, он может быть занят другими операциями, и ответит на запрос на инвалидацию задержкой. Но эта инвалидация в любом случае рано или поздно произойдет. Поэтому, когда нашему кэшу приходит запрос на инвалидацию, он кладет этот запрос в некую очередь, и сразу же отвечает "да, все ничтяк, инвалидировал", а на самом деле инвалидирует его позднее, когда ему будет это удобно сделать. Эта очередь называется invalidate queue.
Эти две хитрости - store buffer и invalidate queue очень здорово ускоряют работу протокола когерентности. Но из-за того, что они по сути асинхронны, кэши разных процессоров могут временно разъезжаться. В итоге то они станут когерентными, но в моменте могут иметь разные значения. Поэтому два одновременных чтения одного и того же адреса на разных ядрах могут вернуть разный результат.
Но что сделать, если я хочу, продолжить исполнение только тогда, когда мою запись гарантированно смогут увидеть все другие ядра? Для этого мне надо убедиться, что моя запись ушла из store buffer в кэш.
А что сделать, если я хочу вычитать максимально актуальное значение текущей переменной? Для это я должен обработать все текущие invalidate запросы, и только потом попробовать вычитать это значение.
Как попросить подсистему памяти сделать это? Для этого у процессоров существуют специальные инструкции (или модификаторы инструкций). Например, для x86 это префикс lock (и другие).
А как попросить процессор выполнить эту инструкцию? Ну либо просто ее вызвать на ассемблере, либо же попросить об этом операционную систему, попросив ее вызвать так называемый барьер памяти, который синхронизирует определенным образом состояние кэша текущего процессора с кэшами других.

VII
Как именно происходит эта синхронизация? Если мне надо убедиться, что запись в кэш завершена, и другие процессору смогут ее увидеть, мне надо дождаться, пока моя запись не уйдет из store buffer в кэш. Но так как записи складываются в store buffer последовательно, к тому моменту, как моя запись уйдет в кэш, в него так же гарантированно уйдут и все предыдущие записи.
А что с чтениями? Что бы убедиться, что следующее чтение вернет актуальное значение, мне надо обработать все запросы на инвалидацию из моей invalidate queue. Но это означает, что к моменту чтения актуального значения, я актуализирую не только саму переменную, но и все остальное, что было в моей invalidate queue. А что там могло быть? Как минимум - все то, что было инвалидировано до соответствующей записи из другого процессора. Поэтому, если одни процессор сделал:

write A
write B
[дождаться сброса B]

А другой сделал:

[дождаться инвалидации всего, что сейчас есть в invalidate queue]
read B

... то второй процессор, увидев обновленное B гарантированно увидит и обновленное A! Ничего не напоминает из JMM?

Подводим промежуточные итоги:
1) Система кэш-память наразрывна, и процессор видит ее как одно целое.
2) Процессор на может читать/писать в обход кэша.
3) Протоколы когерентности кэшей допускают, что "резъезжание" данных между ядрами в моменте, но гарантирует, что все изменения будут рано или поздно видны всем.

VIII
Процессор так же любит реордерить инструкции для ускорения их выполнения. Упомянутые "барьеры памяти" предотвращают такие перестановки.

IX
Теперь перейдем к регистрам. Что это такое? Это небольшая память, находящаяся непосредственно на кристалле процессора. Она может здорово ускорять работу наших программ, так как доступ к данным в регистрах занимает буквально один такт. Для сравнения, доступ к кэшу первого уровня - это около 4 тактов, доступ к кэшу второго уровня - тактов 10-20, и т.д.. Но использовать регистры или нет - это дело разработчика. Теоретически можно работать вообще без регистров общего назначения. То есть оперировать только адресами памяти. И все будет работать. Но медленнее, чем хотелось бы.
Поэтому рагистры активно используют. А кто их использует? Вы вот руками дергаете регистры? Нет. И я нет. А кто их использует? Их использует JVM. Она анализирует ваш код и стремиться сделать так, что бы минимизировать объем данных, прокачиваемых между подсистемой памяти и процессором. Для этого в JIT-компиляторе, который генерирует непосредственно машинный код, есть специальных модуль - Register Allocator. Именно он принимает решение как быть с данными - сохранять их в регистрах или нет. Например, увидев, что у вас рядом идут два чтения одной и той же переменной, register allocator может принять решение на первом чтении сохранить данные значение в регистре, и на втором чтении взять его оттуда, а не лезть в систему "память-кэш" снова.

X
Наконец, JIT может изменять логику вашего кода, что бы минимизировать работу с памятью. Например, если у вас есть цикл

while (x == 0)
sleep(100);

Он может проверить x == 0 один раз, сохранить в регистре значение этого выражения (напр. false), а на следующих итерациях цикла не перечитывать x, а просто брать закэшированный результат.

XI
Что же мне надо сделать, что бы убедиться, что прочитанное сейчас значение является актуальным?
1) Надо обработать invalidate queue на ядре
2) Надо убедиться, что мое чтение не было переставлено в коде с последующими инструкциями компилятором
3) Надо убедиться, что я не подхвачу старое значение их регистров
4) Надо убедиться, что компилятор не сгенерировал хитровысушенный код, откуда это чтение будет просто напросто выпилено.

Как это все сделать за раз? Ответ: volatile. Если мы отметим переменную volatile, то JVM:
1) Не будет сохранять ее в регистрах
2) Не будет оптимизировать код вокруг нее (не будет выпиливать ее чтения, не будет ее переставлять и т.д.)
3) Вокруг ее чтения/записи компилятор добавить специальных инструкций процессора, которые почистят store buffer / invalidate queue кэшей. Обычно это делают через вызов системных функций операционной системы, которая в свою очередь исполнит нужные инструкции процессора.

Это и есть volatile, что называется, "на пальцах".

Заметьте, volatile кэшируются в кэшах, так же, как и все другие переменные. Кэшировать надо все и всегда, так как читать из память очень дорого.
Но для обеспечения правильной видимости, volatile:
1) Форсирует подсистему памяти синхронизировать состояние кэшей.
2) Запрещает JIT-у делать оптимизации на этой переменной.

Поэтому, когда говорят, что "volatile медленный", имеют ввиду не то, что "такие переменные не кэшируются", и не то, что "идет сброс в основую память". Ни того, ни другого нет! Все кэшируется, а "сброс в память" лежит на совести подсистемы памяти, а не на volatile. Имеют ввиду то, что мы теряем время на барьерах, которые синхорнизируют кэши, и на оптимизациях, которые JIT мог бы применить, но не стал этого делать.
...
Рейтинг: 0 / 0
Concurrency Vs multithreading
    #38687907
redwhite90
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
DEVcoach,

спасибо, за подробный ответ и потраченное время. Думаю ешё не раз прочитаю этот текст.

Судя по всему, разхожая фраза о том, что volatile не кешируется относится к тому, что volatile не кешируется в регистрах.
...
Рейтинг: 0 / 0
Concurrency Vs multithreading
    #38688015
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
DEVcoach,

Поэтому, когда говорят, что "volatile медленный", имеют ввиду не то, что "такие переменные не кэшируются", и не то, что "идет сброс в основую память". Ни того, ни другого нет! Все кэшируется, а "сброс в память" лежит на совести подсистемы памяти, а не на volatile. Имеют ввиду то, что мы теряем время на барьерах, которые синхорнизируют кэши, и на оптимизациях, которые JIT мог бы применить, но не стал этого делать.

Большое вам спасибо за развернутый ответ. Это как раз то что я долго хотел сформулировать.

Но в рамках действующего форума лучше не писать так много текста.
...
Рейтинг: 0 / 0
Concurrency Vs multithreading
    #38688071
redwhite90
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
DEVcoach,

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

В этом предложении под процессором понимаетс одно ядро или именно процессор ?
...
Рейтинг: 0 / 0
Concurrency Vs multithreading
    #38688111
cdtyjv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
redwhite90В этом предложении под процессором понимается одно ядро или именно процессор ?Ядро.
...
Рейтинг: 0 / 0
Concurrency Vs multithreading
    #38688211
redwhite90
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
cdtyjv,

я тут вооружился бумагой и ручкой и попытался всё это нарисовать)

У меня что-то похожее получилсь:




я не очень понимаю как контроллер памяти ядра один узнает о существовании переменной в кеше ядра 2.

Какая сущность за это отвечает?
...
Рейтинг: 0 / 0
Concurrency Vs multithreading
    #38688247
redwhite90
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
даже немножко обноылю картинку, но вопрос в силе

...
Рейтинг: 0 / 0
Concurrency Vs multithreading
    #38688267
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
redwhite90, контроллер не знает ни о каких переменных.

Он видит операции с памятью.
...
Рейтинг: 0 / 0
Concurrency Vs multithreading
    #38688274
redwhite90
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
maytonredwhite90, контроллер не знает ни о каких переменных.

Он видит операции с памятью.

что конкретно он видит?
...
Рейтинг: 0 / 0
Concurrency Vs multithreading
    #38688285
cdtyjv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
redwhite90 ,
В целом вы все правильно нарисовали, за исключением связей между invalidate queue и store buffer - их нет. Между кешами есть шина данных. Когда кэш хочет, например, инвалидировать значение в других кэшах, он отправляет соответствующий запрос в шину, другие кэши его подхватывают, и выполняют инвалидацию. Это называется snooping .
Аналогично и с чтением - если вы не находите данные у себя в кэше, вы посылаете запрос в шину. Кэши подхватывают этот запрос, проверяют, есть ли этот адрес у них. Если есть - они выдают его обратно в шину, а запрос в память отменяют.

Это уже слишком низкоуровневые дебри. Если хотите в них въехать, то читайте документацию к конкретным процессорам.
...
Рейтинг: 0 / 0
Concurrency Vs multithreading
    #38688296
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Нужно спуститься на несколько уровней ниже Java.

Скачай любую книжку по Ассемблеру для Intel x86/x64
Есть класс команд (TRANSFER) осуществляющий операции с памятью.

Например

Код: plaintext
1.
MOV [dest],[Source]

в случае когда dest или source являются адресом
пишет или читает атомарную сущность из памяти в регистр или наоборот.

Косвенно из сегмента кода, стека постоянно идёт вычитка и запись
другими командами типа PUSH/POP/CALL.

Вобщем чтива там - непочатый край. Разберись основательно.
...
Рейтинг: 0 / 0
Concurrency Vs multithreading
    #38688353
redwhite90
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
cdtyjv redwhite90 ,
В целом вы все правильно нарисовали, за исключением связей между invalidate queue и store buffer - их нет. Между кешами есть шина данных. Когда кэш хочет, например, инвалидировать значение в других кэшах, он отправляет соответствующий запрос в шину, другие кэши его подхватывают, и выполняют инвалидацию. Это называется snooping .
Аналогично и с чтением - если вы не находите данные у себя в кэше, вы посылаете запрос в шину. Кэши подхватывают этот запрос, проверяют, есть ли этот адрес у них. Если есть - они выдают его обратно в шину, а запрос в память отменяют.

Это уже слишком низкоуровневые дебри. Если хотите в них въехать, то читайте документацию к конкретным процессорам.

Я ниже вашего самого информационно ёмкого сообщения спускаться пока не готов) Но до этого уровня понять очень интересно.

так и у меня на картинке связей между invalidate queue и store buffer нет. Эти стрелки значат, что одноврменно записываем в store buffer и в invalidate queue наши значения. Ещё обратную стрелку не нарисовал означающую, что когда значение исчезло из invalidate queue и обработалось кешем ядра, надо послать сигнал о том, что что кеш инвалидирован и соответственно из другого ядра из store buffer можно будет сделать flush этого значения в кеш.


теперь по этому вопросу
redwhite90я не очень понимаю как контроллер памяти ядра один узнает о существовании переменной в кеше ядра 2.

Какая сущность за это отвечает?

я так понимаю эта сущность это:

авторМежду кешами есть шина данных эта самая "шина кешей"



DEVcoach Когда кэш хочет, например, инвалидировать значение в других кэшах, он отправляет соответствующий запрос в шину, другие кэши его подхватывают, и выполняют инвалидацию. Это называется snooping.

Извиняюсь за занудство, но тут мне кажется важны все детали. ну как минимум по моей картинке инициатором инвалидироваиня кеша выступает контроллер памяти.
...
Рейтинг: 0 / 0
Concurrency Vs multithreading
    #38688395
Basil A. Sidorov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Инвалидация кэша основана на том факте, что у логических схем есть три состояния - ноль, единица и "высокоимпедансное".
В третьем состоянии схема не влияет на шину, но может читать сигналы, которые выставляют на ней другие участники.
Процессор постоянно следит за (общей) шиной адреса и, если обнаруживает адрес, попадающий в его (процессора) кэш - выставляет флаг "строка кэша невалидна", если служебные сигналы показывают, что по адресу делается запись.
Этот механизм работает, если кэш использует сквозную запись, т.к. при отложенной записи модификация строк в кэше процессора не сопровождается сигналами на (общих) шинах адреса/данных.
Есть ньюансы "ядра одного кристала" и "ядра разных кристалов", но тут я подробностей не знаю.
...
Рейтинг: 0 / 0
Concurrency Vs multithreading
    #38688401
Basil A. Sidorov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
redwhite90Извиняюсь за занудство, но тут мне кажется важны все детали. ну как минимум по моей картинке инициатором инвалидироваиня кеша выступает контроллер памяти.Не важны тут детали, пока вы не начнёте самостоятельно разрабатывать оптимизирующий компилятор или/и системные программы.
В языке высокого уровня у вас есть набор примитивов, которыми можно пользоваться вообще не зная, что там происходит в памяти.
...
Рейтинг: 0 / 0
Concurrency Vs multithreading
    #38688407
redwhite90
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
...
Рейтинг: 0 / 0
Concurrency Vs multithreading
    #38688417
redwhite90
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
...
Рейтинг: 0 / 0
Concurrency Vs multithreading
    #38688418
Basil A. Sidorov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Процессор (ядро процессора) - чёрный ящик, у которого "наружу" торчат две шины - адреса и данных.
Эти шины - общие и существуют (аппаратно реализованные) механизмы арбитража, позволяющие корректно использовать эти шины в разных режимах передачи.
"Хренотень внутри", которую вы нарисовали ... Можете забыть о ней. Никто, кроме самого изготовителя процессоров не знает в точности что и как устроено внутри чёрного ящика.
И, что характерно, никому, кроме самого изготовителя этого и не надо знать - всем остальным достаточно "вполне стандартных" примитивов типа "барьер памяти" и "инвалидация кэша". И то и другое может быть гарантировано определёнными машинными командами и порядком их следования в коде.
Да, в теории, знание конкретных детали позволит выжать "последний такт", но это сделает вас таким заложником этих деталей, что epic fail можно будет получить на любой мелочи.

P.S. Прицепил вашу картинку файлом, т.к., например, у меня rghost блокирован как нерекомендованный сайт.
...
Рейтинг: 0 / 0
Concurrency Vs multithreading
    #38688419
redwhite90
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость


гугл то точно рекомендованный)
...
Рейтинг: 0 / 0
Concurrency Vs multithreading
    #38688429
Basil A. Sidorov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
"Наивный чукотский юноша".
...
Рейтинг: 0 / 0
Concurrency Vs multithreading
    #38688437
Basil A. Sidorov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Лично у меня, в Seamonkey, ваши "картинки с другого сайта" просто не отображаются.
Запустив тыртырнет-сексплорер я могу получить ссылку, но это мало что меняет.
...
Рейтинг: 0 / 0
Concurrency Vs multithreading
    #38688449
chabapok
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Blazkowiczredwhite90Что происходит в тот момент, когда я пытаюсь считать волатильную перменную ?
У меня в каждом потоке свое закешированное значение волатильной переменной(непосредственно перед чтением), как они синхронизируются? Как выбирается самое актуальное значение?
P.S. я знаю, что volatile write happens-before volatile read
Грубо говоря на пальцах это так: переменная - это значение в памяти. Кэш это регистр процессора. Обычную переменную можно не читать из памяти (долго), а прочитать из регистра (быстро). Чтение volatile переменной происходит из памяти. Поэтому там актуальное значение, а не из регистра, где может быть устаревшее.

Чуть менее грубо: кроме вышенаписанного, перед записью волатильной переменной из регистра процессора в память, jvm записывает (если есть) все другие регистры в память.
А перед чтением волатильной переменной в регистр из памяти, jvm обновляет остальные регистры из памяти.

поэтому записанное перед записью в волатил видится после чтения из волатила.
...
Рейтинг: 0 / 0
Concurrency Vs multithreading
    #38688454
redwhite90
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Ну хотя бы не буду теперь чувствовать себя идиотом, когда начинаются холливары про volatile. Причем обычно у отвечающего хватает ответить что то типа "чувак, ты не прав", там все по другому, на вопрос как кто нить кинет ссылку, которую даже сам не читал. Если кто то пытается объяснить своими словами. Его массово заклевывают, мол ты не прав, но доходчиво на общепонятных(понятных спрашивающему) примитивах никто не удосужится.
...
Рейтинг: 0 / 0
Concurrency Vs multithreading
    #38688455
Basil A. Sidorov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Лично я не стал бы полагаться на это поведение.
Volatile даёт определённые гарантии относительно конкретной переменной.
Ладушки, а всё остальное - от лукавого.
...
Рейтинг: 0 / 0
Concurrency Vs multithreading
    #38688462
cdtyjv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Basil A. SidorovЛично я не стал бы полагаться на это поведение.
Volatile даёт определённые гарантии относительно конкретной переменной.
Ладушки, а всё остальное - от лукавого.Сила volatile как раз и строится на piggibacking:
int x = 0;
volatile int y = 0;

Thread1:
x = 1;
y = 1;

Thread2:
if (y == 1)
assert x == 1;

Это очень мощная фича, которая очень широко применяют в конкурентном программировании. Ничего в ней "лукавого" нет.
...
Рейтинг: 0 / 0
Concurrency Vs multithreading
    #38688465
Basil A. Sidorov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
И, типа, от порядка объявления-следования ничего не зависит? Совсем-совсем?
...
Рейтинг: 0 / 0
Concurrency Vs multithreading
    #38688466
redwhite90
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
cdtyjv,
про piggyback я тоже слышал.

http://stackoverflow.com/questions/8769570/volatile-piggyback-is-this-enough-for-visiblity

но минус в том, что если кто-то подумает, что это действие над волатильной переменной не нужно больше(не подумав даже о том волатильная она или нет), удалит одну строчку - всё может накрыться)

chabapok Чуть менее грубо: кроме вышенаписанного, перед записью волатильной переменной из регистра процессора в память, jvm записывает (если есть) все другие регистры в память.
А перед чтением волатильной переменной в регистр из памяти, jvm обновляет остальные регистры из памяти.

поэтому записанное перед записью в волатил видится после чтения из волатила.

хм, вижу противоречие...

то есть волатильная переменная по вашему пишется в регистр процессора?
...
Рейтинг: 0 / 0
Concurrency Vs multithreading
    #38688472
redwhite90
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
DEVcoach,

DEVcoachКак это все сделать за раз? Ответ: volatile. Если мы отметим переменную volatile, то JVM:
1) Не будет сохранять ее в регистрах
2) Не будет оптимизировать код вокруг нее (не будет выпиливать ее чтения, не будет ее переставлять и т.д.)
3) Вокруг ее чтения/записи компилятор добавить специальных инструкций процессора, которые почистят store buffer / invalidate queue кэшей. Обычно это делают через вызов системных функций операционной системы, которая в свою очередь исполнит нужные инструкции процессора.

Это и есть volatile, что называется, "на пальцах".

Заметьте, volatile кэшируются в кэшах, так же, как и все другие переменные. Кэшировать надо все и всегда, так как читать из память очень дорого.
Но для обеспечения правильной видимости, volatile:
1) Форсирует подсистему памяти синхронизировать состояние кэшей.
2) Запрещает JIT-у делать оптимизации на этой переменной.

а можете по каждому пункту предоставить прувы, а то смотрю мнения расходятся.
...
Рейтинг: 0 / 0
Concurrency Vs multithreading
    #38688474
cdtyjv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Basil A. SidorovИ, типа, от порядка объявления-следования ничего не зависит? Совсем-совсем?Не понял вопрос.
...
Рейтинг: 0 / 0
Concurrency Vs multithreading
    #38688477
Basil A. Sidorov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
cdtyjvНе понял вопрос.Переставили местами порядок объявления переменных, порядок следования операторов в тексте программы.
Есть класс с кучей переменных. Если одна единственная volatile выключит оптимизацию всего остального, то не пошло бы оно лесом - такое поведение?
На каком фрагменте действует volatile?
...
Рейтинг: 0 / 0
Concurrency Vs multithreading
    #38688478
questioner
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
говорят, что понять как работает волатайл можно по следующему коду

http://hg.openjdk.java.net/icedtea/jdk7/hotspot/file/d9f0ed25f7ed/src/share/vm/opto/memnode.cpp#l2862

кто знает ассемблер -расскажите что там написано)
...
Рейтинг: 0 / 0
Concurrency Vs multithreading
    #38688479
cdtyjv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
redwhite90а можете по каждому пункту предоставить прувы, а то смотрю мнения расходятся.Ну давайте для большей точности вот так скажем:

1) Не будет сохранять ее в регистрах
2) Не будет оптимизировать код вокруг нее (не будет выпиливать ее чтения, не будет ее переставлять и т.д.)
3) Вокруг ее чтения/записи компилятор добавить специальных инструкций процессора, которые почистят store buffer / invalidate queue кэшей. Обычно это делают через вызов системных функций операционной системы, которая в свою очередь исполнит нужные инструкции процессора.

Ибо п.1 - это по сути одна из оптимизаций из п.2. Здесь принципиально то, что каждое чтение волатильной переменной должно сопровождаться ее реальным чтением из подсистемы "кэш-память". А сохраняет ее процессор для каких-то своих нужд в регистры или нет - дело третье. Хочет сохранить - ну пускай сохранит.
Например, предположим, что у нас есть следующий код:
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
volatile int x;

void method1() {
    method2(x);
}

method2(int val) {
   ...;
}



И вы вызываете method1(). Как будет выглядеть assembly? Может быть так:

Код: java
1.
2.
push [x address]; // Записали копию волатильной переменной в стэк.
call method2; // Вызвали метод.


А может быть вот так:

Код: java
1.
2.
mov r11, [x address]; // Сохранили копию волатильной переменной в регистр.
call method2; 

// Вызвали метод.

Первый способ - стандартный, специфицированный подход к вызову функций.
Второй способ - более быстрая вариация, так называемый fastcall, так как быстрее сохранить переменную в регистр, чем записывать ее в стэк.
Но в обоих случаях была создана копия волатильной переменной. Это страшно? Нет, ведь мы передаем int в метод, а примитивы передаются в методы по значению. То есть у нас просто напросто нет другого варианта, кроме как скопировать волатильную переменную.

Но если бы переменная не была волатильной, то во втором случае JVM могла бы попробовать переиспользовать ее из регистра при последующем чтении. А если она волатильна, то такого переиспользования не будет.

Так что не циклитесь на регистрах. Это детали.
...
Рейтинг: 0 / 0
Concurrency Vs multithreading
    #38688480
cdtyjv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
questionerговорят, что понять как работает волатайл можно по следующему коду
http://hg.openjdk.java.net/icedtea/jdk7/hotspot/file/d9f0ed25f7ed/src/share/vm/opto/memnode.cpp#l2862
кто знает ассемблер -расскажите что там написано)Это кишки компилятора, они вам никак не помогут понять volatile.
...
Рейтинг: 0 / 0
Concurrency Vs multithreading
    #38688481
cdtyjv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Basil A. SidorovПереставили местами порядок объявления переменных, порядок следования операторов в тексте программы.
Есть класс с кучей переменных. Если одна единственная volatile выключит оптимизацию всего остального, то не пошло бы оно лесом - такое поведение?
На каком фрагменте действует volatile?volatile не выключает "все остальное". Она синхронизирует состояние в момент ее чтения/записи. До/после этого можно оптимизировать все, что угодно.
...
Рейтинг: 0 / 0
Concurrency Vs multithreading
    #38688482
redwhite90
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
cdtyjv,

вроде пазл сошёлся)
...
Рейтинг: 0 / 0
Concurrency Vs multithreading
    #38688487
Basil A. Sidorov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
cdtyjvvolatile не выключает "все остальное". Она синхронизирует состояние в момент ее чтения/записи. До/после этого можно оптимизировать все, что угодно.Я, таки, нашёл How will the JMM change under JSR 133 и понял то, о чём вы говорите.
Возражения против использования такого подхода в прикладном коде - остаются: завтра автор (по забывчивости) или кто другой (по незнанию) переставит местами два оператора потому, что это "эстетичнее", а на работу алгоритма в текущем потоке - никак не влияет. И всё - синхронизация с другими потоками разрушена.
...
Рейтинг: 0 / 0
Concurrency Vs multithreading
    #38688493
Basil A. Sidorov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
И, кстати, даже без переупорядочивания ...
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
class Shared {
  int a, b;
  volatile int v;
  a = b = v = 0;
/* куча кода */
  a = b = v = 1;
  ? v : log( "Хай " + a) : log( "Нехай " + b );
/* гарантируется, что все потоки будут читать из памяти новые значения*/
}

Вроде - всё хорошо.
Но а и б "на трубе не сидят" и JIT невозбранно может кешировать их в регистрах.
Если такое кэширование произошло до записи "изменчивой" переменной, то её перечитывание из памяти (само по себе) не отменит регистровые копии.
...
Рейтинг: 0 / 0
Concurrency Vs multithreading
    #38688498
Basil A. Sidorov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Мой пример - некорректный, но дальше думать, т.к. возражения всё равно остаются.
...
Рейтинг: 0 / 0
Concurrency Vs multithreading
    #38688501
Basil A. Sidorov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
class Shared {
  int b = 0;
  volatile v = 0;
  int test() {
    if ( unique() ) b = 1;
    v = 2;
    return b + 3;  // никаких гарантий, что в другом потоке (тоже) будет четыре
  }
}

Пример идиотский, но суть проблемы, думаю понятна: изменчивость - плохой барьер.
...
Рейтинг: 0 / 0
Concurrency Vs multithreading
    #38688510
cdtyjv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Basil A. Sidorov
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
class Shared {
  int b = 0;
  volatile v = 0;
  int test() {
    if ( unique() ) b = 1;
    v = 2;
    return b + 3;  // никаких гарантий, что в другом потоке (тоже) будет четыре
  }
}

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

Вашей претензией является неочевидность. С этим никто и не спорит. Но с другой стороны, никто и не говорит, что этот подход надо использовать в регулярной практике. Piggibacking часто применяют в замысловатых неблокирующих алгоритмах, когда хотят максимально расслабить синхронизацию, и т.д.. Рядовой программист, который может бездумно "переставить две строчки" в такой код не полезет.
Для сложных задач - сложный код, для простых - простой.
...
Рейтинг: 0 / 0
Concurrency Vs multithreading
    #38688515
Basil A. Sidorov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
cdtyjvВашей претензией является неочевидность. С этим никто и не спорит. Но с другой стороны, никто и не говорит, что этот подход надо использовать в регулярной практикеСтранные вы люди ...
Зачем обсуждать (реально) тёмные детали устройства процессора, если всё, что достаточно знать об изменчивости, укладывается вот в это предложение:Fixing the Java Memory ModelThis process guarantees that when a variable is written by one thread during a synchronized block protected by a given monitor and read by another thread during a synchronized block protected by the same monitor, the write to the variable will be visible by the reading thread?
Т.е. раньше гарантии видимости распространялись только на саму переменную, теперь - на все предыдущие присваивания. Что улучшает синхронизацию, за счёт незначительной просадки производительности.

P.S. А пример мой относился к тому, что JIT имеет полное право модифицировать код до:
Код: sql
1.
2.
3.
4.
5.
6.
7.
boolean test() {
  boolean tmp = unique();
  if (tmp) b = 1;
  v = 2;
  if (tmp) return 4;
  else return 3;
}

Однопоточная семантика осталась прежней, многопоточная - разрушена.
...
Рейтинг: 0 / 0
Concurrency Vs multithreading
    #38688518
cdtyjv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Basil A. SidorovЗачем обсуждать (реально) тёмные детали устройства процессора, если всё, что достаточно знать об изменчивости, укладывается вот в это предложение:Fixing the Java Memory ModelThis process guarantees that when a variable is written by one thread during a synchronized block protected by a given monitor and read by another thread during a synchronized block protected by the same monitor, the write to the variable will be visible by the reading thread?
Т.е. раньше гарантии видимости распространялись только на саму переменную, теперь - на все предыдущие присваивания. Что улучшает синхронизацию, за счёт незначительной просадки производительности.Всего существует два "типа синхронизации":
1) Release semantics - после записи некоторой переменной она становится потенциально видна другим потокам, так же, как и все записи, которые шли до нее.
2) Acquire semantics - после чтения некоторой переменной, все последующие чтения других переменных должны вычитать более новые значения "себя".

Все, другого не дано. Предложение, которое вы привели описывает только synchronized. А работает он так:
acquire()
тело_synzcronized_блока
release()

volatile работает вот так:
запись_volatile_переменной
release()

acquire()
чтение_volatile_переменной

Соответственно, все те трюки с piggibacking, которые возможны с volatile, возможны и с synchronized. Вот это работает:
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
int x;
int y;

Thread 1:
x = 1;

synchronized {
    y = 1;
}


Thread 2:
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
bool flag;

synchronized {
    flag = y == 1;
}

if (flag)
    assert x == 1;



Что бы не верить на слово, что оно работает именно так, а понимать почему оно именно так было спроектировано и именно так работает, и надо знать и про JIT, и про store buffer / invalidate queue. Это улучшает понимание протекающих процессов, а от этого еще никому хуже не стало.

Basil A. SidorovОднопоточная семантика осталась прежней, многопоточная - разрушена.Ничего не разрушено ... так как в вашем примере многопоточная семантика изначально была некорректной. Нечего разрушать. Предлагаю оставить этот бессмысленный пример, и рассматривать что-то реально применимое.
...
Рейтинг: 0 / 0
Concurrency Vs multithreading
    #38688550
chabapok
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
redwhite90chabapok Чуть менее грубо: кроме вышенаписанного, перед записью волатильной переменной из регистра процессора в память, jvm записывает (если есть) все другие регистры в память.
А перед чтением волатильной переменной в регистр из памяти, jvm обновляет остальные регистры из памяти.
поэтому записанное перед записью в волатил видится после чтения из волатила.

хм, вижу противоречие...
то есть волатильная переменная по вашему пишется в регистр процессора?
Не очень понял контекст вопроса. Но вцелом да: процессору, чтобы выполнить какую-либо операцию над двумя переменными, надо как минимум одну загрухить в регистр, и результат операции оказывается в регистре. Так, чтобы произвести операцию над двумя ячейками памяти и результат записать сразу в память - в х86 такого нет. И даже если где-то и есть, это большая редкость.
То есть да, волатил когда-нибудь в регистр пишется, если операции над волатилом есть.
...
Рейтинг: 0 / 0
Concurrency Vs multithreading
    #38688551
chabapok
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
cdtyjvНапример, предположим, что у нас есть следующий код:
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
volatile int x;

void method1() {
    method2(x);
}

method2(int val) {
   ...;
}



И вы вызываете method1(). Как будет выглядеть assembly? Может быть так:

Код: java
1.
2.
push [x address]; // Записали копию волатильной переменной в стэк.
call method2; // Вызвали метод.


А может быть вот так:

Код: java
1.
2.
mov r11, [x address]; // Сохранили копию волатильной переменной в регистр.
call method2; 

// Вызвали метод.

Первый способ - стандартный, специфицированный подход к вызову функций.
Второй способ - более быстрая вариация, так называемый fastcall, так как быстрее сохранить переменную в регистр, чем записывать ее в стэк.
Но в обоих случаях была создана копия волатильной переменной. Это страшно? Нет, ведь мы передаем int в метод, а примитивы передаются в методы по значению. То есть у нас просто напросто нет другого варианта, кроме как скопировать волатильную переменную.

Ваш пример ни при чем. В вашем примере чтение волатила происходит однократно - при передаче в функцию. А в функции х уже будет гарантированно непоменян другим потоком, т.к. это уже локальная переменная. Если мы хотим видеть волатильный х, наш "другой вариант": передавать в method2 this и обращаться к полю x обьекта.



cdtyjvНо если бы переменная не была волатильной, то во втором случае JVM могла бы попробовать переиспользовать ее из регистра при последующем чтении. А если она волатильна, то такого переиспользования не будет.
для конкретно вашего примера - нет. Переиспользование будет, поскольку переменные передаются по значению, а значение не волатильно. Т.е. внутри функции method2 наше "икс" локально, т.е.ни о какой волатильности не может идти речи.
...
Рейтинг: 0 / 0
Concurrency Vs multithreading
    #38688557
cdtyjv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
chabapokВаш пример ни при чем. В вашем примере чтение волатила происходит однократно - при передаче в функцию. А в функции х уже будет гарантированно непоменян другим потоком, т.к. это уже локальная переменная. Если мы хотим видеть волатильный х, наш "другой вариант": передавать в method2 this и обращаться к полю x обьекта.Мой пример - опровержение моего же тезиса о том, что "волатильные переменные не сохраняются в регистрах". Сохраняются.

chabapokдля конкретно вашего примера - нет. Переиспользование будет, поскольку переменные передаются по значению, а значение не волатильно. Т.е. внутри функции method2 наше "икс" локально, т.е.ни о какой волатильности не может идти речи.Я имел ввиду следующий сценарий переиспользования:
Код: java
1.
2.
3.
4.
5.
6.
7.
method1() {
    method2(x);

    if (x == ...) { // Второе чтение, x может быть переиспользован из регистра, если не volatile
        ...
    }
}
...
Рейтинг: 0 / 0
Concurrency Vs multithreading
    #38688564
Basil A. Sidorov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
cdtyjvНичего не разрушено ... так как в вашем примере многопоточная семантика изначально была некорректнойПравильно, некорректной.
Что плавно подводит к другой мысли: задолго до того, как нас начнут мучать особенности поведения изменчивых переменных - мы должны научиться писАть многопоточный код, который корректен в принципе .
Т.е. снова - ну вот нахрена все эти домыслы об устройстве процессора, если к созданию корректного кода это не приближает ни на шаг?
...
Рейтинг: 0 / 0
Concurrency Vs multithreading
    #38688769
Фотография Usman
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Basil A. Sidorovну вот нахрена все эти домыслы об устройстве процессораДля понимания разницы между данными, которые находятся в основной памяти (актуальные) и в кэше (возможно "устаревшие").
...
Рейтинг: 0 / 0
Concurrency Vs multithreading
    #38688773
Basil A. Sidorov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
UsmanДля понимания разницы между данными, которые находятся в основной памяти (актуальные) и в кэше (возможно "устаревшие").Зачем требуется понимание этой разницы, если простая оптимизация может использовать (регистровую) переменную которая "уже устарела"?
Или даже так: зачем требуется объяснять детали устройства аппаратуры, если точность такого объяснения сомнительна?
...
Рейтинг: 0 / 0
130 сообщений из 130, показаны все 6 страниц
Форумы / Java [игнор отключен] [закрыт для гостей] / Concurrency Vs multithreading
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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