Это 29-й день моего участия в Gengwen Challenge.Подробности о мероприятии:Обновить вызов.
Сразу после предыдущегоПривет, можешь рассказать о ключевом слове volatile? (Четыре)
4.6 happens-before
В принципе должно бытьJMM
глава говорит,happens-before
ПринципJMM
основные понятия. Но поскольку все дело в наглядности и порядке, давайте сначала кратко упомянем об этом.
Принцип «происходит до» гласит, что предыдущая операция должна быть видна последующей операции. Другими словами, соблюдение этого правила в многопоточной среде может обеспечить видимость общих переменных для нескольких операций.
4.6.1 happens-before
&& as-if-serial
happens-before
взаимоотношения в природе иas-if-serial
Семантика — это одно и то же.
-
happens-before
а такжеas-if-serial
Убедитесь, что результаты многопоточного и однопоточного выполнения не изменились соответственно. -
as-if-serial
Видимость, которую семантика создает для пользователя, состоит в том, что в последовательности программы выполняется один поток;happens-before
Внешний вид, вызванный семантикой, положительный Правильно синхронизированная многопоточная программаhappens-before
выполняются в указанном порядке.
Цель этих двух правил — максимально улучшить параллелизм выполнения программы без изменения результата выполнения программы.
4.6.2 happeds-before
правило
**"JSR-133: Модель памяти Java и спецификация потоков"** определяет следующие правила "происходит до".
Правила порядка выполнения программы: каждая операция в потоке выполняется до любых последующих операций в этом потоке.
правила порядка программыПроще говоря, чтобы обеспечить параллелизм, вы можете оптимизировать и настроить порядок выполнения так, как вам хочется, но результат всегда один и тот же. Это общая программа.
Следите за правилами блокировки: отпирание замка происходит до последующего запирания замка.
Правила блокировки монитора
static int y = 1;
static void testMonitorRule(){
synchronized(Object.class){
if(y==1){
y=2;
}
}
}
Поток 1 получает блокировку первым и изменяет значение y на 2. После того, как поток 2 получает блокировку, он может непосредственно видеть, что y==2.
Правила для изменчивых переменных: запись в изменчивое поле происходит до любой последующей записи в изменчивое поле. читать.
правила изменяемой переменной
static int i = 1;
static volatile boolean flag = false;
static void testVolatileRuleReader(){
i=2;//1
flag=true;//2
}
static void testVolatileRuleWriter(){
if(flag){//3
assert i == 2;//4
}
}
Итак, шаг 3 — это чтение, и вы можете увидеть запись шага 2.
Переходный: если А происходит раньше В, а В происходит раньше С, то А происходит раньше С.
транзитивное правило, чуть вышеvolatile
В примере правила говорится, что шаг 1 должен произойти до шага 4.
правило start(): если поток A выполняет операцию ThreadB.start() (запускает поток B), то Операция ThreadB.start() происходит перед любой операцией в потоке B.
правила запуска()
static void testStartRule(){
AtomicInteger x = new AtomicInteger(1);
final Thread t = new Thread(() -> {
assert x.get() == 2;
});
x.set(2);
t.start();
}
Основной поток вызывает дочерний потокt.start()
Все предыдущие операции с общими переменными видны дочерним потокам.
Правило join(): если поток A выполняет операцию ThreadB.join() и успешно возвращается, то любая операция в потоке B происходит до того, как поток A успешно вернется из операции ThreadB.join().
правила присоединения()
static void testJoinRule() throws InterruptedException {
AtomicInteger x = new AtomicInteger(1);
final Thread t = new Thread(() -> {
try {
TimeUnit.SECONDS.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
x.set(2);
});
t.start();
t.join();
assert x.get() == 2;
}
вызвать дочерний поток в основном потокеt.join()
, все изменения общих переменных дочерними потоками видны основному потоку.
5 Резюме
5.1 volatile
сценарии использования
volatile
существуетJava
Он часто используется в параллелизме, напримерAtomic
в упаковкеvalue
,так же какAbstractQueuedLongSynchronizer
серединаstate
переменныеvolatile
Украшено, чтобы гарантировать видимость памяти.
В нашем процессе разработки также есть некоторые приложения, такие как.
Используйте один поток, чтобы остановить другой поток, изменив бит флага
public static volatile boolean run = true;
public static void main(String[] args) throws InterruptedException {
final Thread t = new Thread(() -> {
int i = 0;
while (!run) {
i++;
Thread.yield();
}
});
t.start();
TimeUnit.SECONDS.sleep(10);
run= true;
}
Блокировки с двойной проверкой реализуют шаблон singleton.
public class DoubleCheckingLock {
private static volatile Instance instance;
public static Instance getInstance(){
if(instance == null){
synchronized (DoubleCheckingLock.class){
if(instance == null){
instance = new Instance();
}
}
}
return instance;
};
static class Instance { }
}
В частности, как этого добиться, см. ** "Искусство параллельного программирования на Java"** в этой хорошей книге.
5.2 Закрытие
Эта статья начинается с примера и приводит к проблемам видимости и порядка работы с общими переменными в многопоточной среде. В сочетании с аппаратной средой анализируется, что для эффективного использования ресурсов компьютера и улучшения параллелизмаCPU
Кэширование было введено, чтобы вызвать проблемы. Чтобы решить проблему согласованности, вызванную кешем, была проанализирована еще одна волна.MESI
Соглашение было окончательно проанализировано.volatile
Основной принцип内存屏障
.
На вопросы, упомянутые в начале статьи, можно будет ответить уже после прочтения этой статьи. оsynchronized
Вопрос в этой частиsynchronized
Анализ воссоединения глав.
Брат, не паникуй! Не стесняйтесь оставлять лайки, обсуждать и комментировать. Добро пожаловать в колонку интервьюНе паникуйте, когда сталкиваетесь | Параллельное программирование на Java, Не беспокойтесь о повышении зарплаты во время собеседования. Также добро пожаловать, чтобы следовать за мной, я должен быть лучшим человеком.