JavaRush /Java-Blog /Random-DE /Level 27. Antworten auf Interviewfragen zum Levelthema
DefNeo
Level 36

Level 27. Antworten auf Interviewfragen zum Levelthema

Veröffentlicht in der Gruppe Random-DE
Level 27. Antworten auf Interviewfragen zum Thema Level - 1
  1. Was ist ein Deadlock?

    Ein Deadlock ist eine Situation, in der zwei oder mehr Threads blockiert sind und aufeinander warten. Deadlock wird auch Deadlock genannt.

    Deadlock ist eine Situation, in der zwei oder mehr Prozesse, die einige Ressourcen belegen, versuchen, andere Ressourcen zu erhalten, die von anderen Prozessen belegt sind, und keiner der Prozesse die benötigte Ressource belegen und dementsprechend die belegte freigeben kann.

    Es gibt Deadlocks in der Synchronisationsreihenfolge (die durch Auftragszuweisung gelöst werden);

    Deadlock zwischen Objekten (verschiedene Objekte versuchen, auf dieselben synchronisierten Blöcke zuzugreifen);

    Ressourcen-Deadlock (beim Versuch, auf einige Ressourcen zuzugreifen, die jeweils nur ein Thread verwenden kann).

  2. Welche Strategien kennen Sie, um das Auftreten von Deadlocks zu verhindern?

    Wenn der Code fehlerfrei geschrieben wird, gibt es natürlich keine Deadlocks. Aber wer kann garantieren, dass sein Code fehlerfrei geschrieben ist? Natürlich hilft das Testen, einen erheblichen Teil der Fehler zu identifizieren, aber wie wir bereits gesehen haben, sind Fehler in Multithread-Code nicht einfach zu diagnostizieren und selbst nach dem Testen kann man nicht sicher sein, dass es keine Deadlock-Situationen gibt. Können wir uns irgendwie vor Blockaden schützen? Die Antwort ist ja. Ähnliche Techniken werden in Datenbank-Engines verwendet, die häufig Deadlocks (im Zusammenhang mit dem Transaktionsmechanismus in der Datenbank) beheben müssen. Die Lockim Paket verfügbare Schnittstelle und ihre Implementierungen java.util.concurrent.locksermöglichen es Ihnen, mithilfe der Methode zu versuchen, den einer Instanz dieser Klasse zugeordneten Monitor zu belegen tryLock(gibt true zurück, wenn der Monitor belegt werden konnte).

    Es gibt auch eine Strategie für die Verwendung offener Aufrufe, also des Aufrufs von Methoden anderer Objekte außerhalb des synchronisierten Blocks.

    Link zum Artikel: Deadlock in Java und Methoden zu seiner Bekämpfung

  3. Kann es bei der Verwendung von Methoden zu Deadlocks kommen wait-notify?

    Für mich persönlich ist es schwierig, diese Frage zu beantworten, aber nachdem wir verschiedene Diskussionen zu diesem Thema im Internet gelesen haben, können wir Folgendes sagen:

    synchronizedDeadlocks können durch die sinnvolle Verwendung von , volatile, monitor ( wait(), notify(), ) vermieden werden notifyAll(), und wenn Sie tiefer graben, dann verwenden Sie Klassen java.utils.concurrent: anstelle gewöhnlicher Sammlungen – Multithread-Optionen ( ConcurrentHashMapzum Beispiel); Wenn Sie eine komplexere Methode zum Synchronisieren von Threads benötigen – anders CyclicBarrier, CountDownLatch.

    waitWenn Sie - richtig verwenden notify, sollten keine Deadlocks auftreten.)))

    Hier ist der Link: Deadlock oder Deadlock.

  4. Was wird häufiger verwendet: notifyoder notifyAll?

    java.lang.Object.notify() weckt einen einzelnen Thread, der auf dem Monitor dieses Objekts wartet. Wenn Threads auf dieses Objekt warten, wird einer von ihnen zum Aktivieren ausgewählt. Die Auswahl ist willkürlich und liegt im Ermessen der Implementierung. Ein Thread wartet auf dem Monitor eines Objekts, indem er eine der Wartemethoden aufruft.

    Diese Methode sollte nur von einem Thread aufgerufen werden, der Eigentümer des Monitors dieses Objekts ist. Ein Thread wird auf drei Arten Eigentümer des Objektmonitors:

    • Durch Ausführen einer synchronisierten Instanzmethode dieses Objekts.
    • Durch Ausführen des Hauptteils einer synchronisierten Anweisung, die das Objekt synchronisiert.
    • Für Objekte vom Typ Klasse durch Ausführen einer synchronisierten statischen Methode dieser Klasse.

    Es kann jeweils nur ein Thread Eigentümer des Monitors eines Objekts sein.

    java.lang.Object.notifyAll() weckt alle Threads, die auf dem Monitor dieses Objekts warten. Ein Thread wartet auf dem Monitor eines Objekts, indem er eine der Wartemethoden aufruft.

    Die aktivierten Threads können nicht fortfahren, bis der aktuelle Thread die Sperre für dieses Objekt aufhebt. Die aktivierten Threads konkurrieren auf die übliche Weise mit allen anderen Threads, die möglicherweise aktiv um die Synchronisierung auf diesem Objekt konkurrieren. Beispielsweise genießen die aktivierten Threads keine verlässlichen Privilegien oder Nachteile, da sie der nächste Thread sind, der dieses Objekt sperrt.

    Diese Methode sollte nur von einem Thread aufgerufen werden, der Eigentümer des Monitors dieses Objekts ist.

    Es handelt sich um Auszüge aus der Dokumentation. Die Frage ist meist rhetorischer Natur, je nach Anwendung, je nach Situation))) Ich weiß nicht einmal, wie ich antworten würde. Wenn jemand eine Vermutung hat, hinterlassen Sie sie bitte in den Kommentaren. Ich freue mich sehr, sie zu lesen.

  5. Die Methode waitempfiehlt sich für den Einsatz bei Konstruktionen ifoder while?

    Здесь отвечу просто цитатой из сайта: Синхронизация потоков

    По поводу вызова метода wait. Это уже из разряда чистой техники. Рекомендуется вызывать wait изнутри цикла while. Т.е., писать не

    if (some condition){
        obj.wait()
    }

    ..., а

    while (some condition){
        obj.wait()
    }

    Зачем это надо. Дело в том, что notify может вызвать кто угодно. Просто по ошибке, от которой никто не застрахован. В том случае из опыта, о котором я рассказывал выше, мы взялись за переделку именно для того, чтобы избежать такой возможности. Просто спрятали ein Objekt, на котором происходит синхронизация. И доступ к нему имел только наш Code. Это хорошая практика, но не всегда возможно, к сожалению. Так вот, если поток ждет выполнения некоторого условия – вариант с while надежнее. Если поток пустoder по ошибке – он опять проверит Zustand и, если надо, будет ждать дальше.

    Кроме того, не исключена возможность и простого выхода из ожидания без вызова notify. Я честно признаюсь, что не видел этого в спецификации виртуальной машины, хотя специально искал. Но некоторые «гуру» утверждают, что VM может выйти из состояния ожидания самопроизвольно. И более того, периодически это наблюдается. Если кто-нибудь даст ссылку на соответствующую спецификацию – буду благодарен!

  6. Was происходит после вызова метода notifyAll?

    The java.lang.Object.notifyAll() wakes up all threads that are waiting on this object's monitor. A thread waits on an object's monitor by calling one of the wait methods.

    Пробуждает все нити, которые ждали на этом мониторе.

  7. Какие выгоды получает ein Objekt, если он immutable?

    Нашел комментарий на: immutable-ein Objektы и многопоточность

    Immutable ein Objekt — это ein Objekt, состояние которого после создания невозможно изменить. В случае Java это значит что все поля экземпляра у класс отмечены Wie final и являются примитивами oder тоже immutable типами.

    Пример:

    public class ImmutablePoint {
        private final int x;
        private final int y;
        private final String description;
    
        public ImmutablePoint(int x, int y, String description) {
            this.x = x;
            this.y = y;
            this.description = description;
        }
    }

    После создания экземпляра ImmutablePoint его модификация невозможна.

    Простейший пример immutable класса из JDK это String. Любые методы, которые вы вызовите на строке (например description.toLowerCase()) вернут новую строку, а не модифицируют исходную.

    Пример mutable класс из JDK — Date. Например myDate.setHours(x) модифицирует сам экземпляр myDate!

    Есть разница между immutable-ein Objektом (то есть, неизменяемым), и final-ссылкой.

    Ключевое слово final для ein Objektных типов гарантирует неизменяемость лишь ссылки, но не самого ein Objektа. Например, если у вас есть final-Verknüpfung на ArrayList<T>, вы тем не менее можете добавлять в него новые элементы oder изменять существующие.

    В случае же immutable-ein Objektа ein Objekt после окончания конструктора не изменяется вообще. Одного лишь модификатора final для этого недостаточно, необходимо, чтобы все подein Objektы были тоже неизменяемыми. Вы в принципе можете держать внутри ссылку на изменяемый ein Objekt, но обращаться с ним так, чтобы он не менялся.

    Использование неизменяемых ein Objektов даёт много выгод. Например, о таком ein Objektе намного легче судить в ситуации, когда во многих частях программы есть Verknüpfung на него (для изменяемого ein Objektа, любая часть программы может вызвать мутирующую функцию в практически любой момент времени и из любого потока).

    Но то, что для нас важно в контексте вопроса — неизменяемые ein Objektы не требуют синхронизации при многопоточном доступе. Вот собственно и вся рекомендация: используйте неизменяемые ein Objektы, и вам не придётся думать о том, что нужно, а что не нужно синхронизировать. Единственная возможная проблема — если вы внутри ещё не отработавшего конструктора публикуете ссылку на ein Objekt, через которую к нему может получить доступ кто-нибудь ещё, и увидеть ein Objekt в изменяющемся состоянии! (Это бывает не так уж и редко. Например, иногда программист хочет добавить ein Objekt в конструкторе в коллекцию всех ein Objektов данного типа.)


    Следует различать действительно неизменяемые ein Objektы, и ein Objektы, имеющие лишь интерфейс «только для чтения». При чтении ein Objekt тем не менее может менять свою внутреннюю структуру (например, кэшировать самый свежий Anfrage данных). Такие ein Objektы не являются в строгом смысле неизменяемыми, и не могут быть использованы из разных потоков без предосторожностей. (Поэтому, если ваш ein Objekt включает другие ein Objektы, убедитесь, что dokumentierenация гарантирует их неизменяемость!)


    Обратите внимание, что для полей неизменяемого ein Objektа вы практически обязаны использовать final! Дело в так называемой безопасной публикации. Смотрите. Инструкции в Java-программе могут быть переставлены Wie оптимизатором, так и процессором (у Java достаточно слабая модель памяти). Поэтому, если не предпринимать специальных действий, окончание работы конструктора и присвоение значений полям может быть переставлено (но невидимо в рамках текущего потока)! Использование final гарантирует, что такого не произойдёт.

    В случае многопоточного программирования преимущества immutable классов очевидны: после создания ein Objektы можно передавать другим потокам и они всегда будут в актуальном состоянии. Т.е. вам не надо проверять не устарело ли состояние вашего экземпляра и не модифицировал ли его другой поток пока вы с ним работаете. Например, у вас есть метод bill(Date endDate), в нём вы наивно проверяете соответствие endDate Wieим-то предварительным условиям и начинаете с ней работать. В этот момент другой поток может изменить endDate, например установит её глубоко в прошлое. Последствия могут быть самыми удивительными.

  8. Was такое «thread-safe»?

    Опять же: What is thread Safe in java? [duplicate]

    Thread safe means that a method or class instance can be used by multiple threads at the same time without any problems occuring.

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

    Consider the following method:

    private int myInt = 0;
    public int AddOne()
    {
        int tmp = myInt;
        tmp = tmp + 1;
        myInt = tmp;
        return tmp;
    }

    Now thread A and thread B both would like to execute AddOne(). but A starts first and reads the value of myInt (0) into tmp. Now for some reason the scheduler decides to halt thread A and defer execution to thread B. Thread B now also reads the value of myInt (still 0) into it's own variable tmp. Thread B finishes the entire method, so in the end myInt = 1. And 1 is returned. Now it's Thread A's turn again. Thread A continues. And adds 1 to tmp (tmp was 0 for thread A). And then saves this value in myInt. myInt is again 1.

    Здесь и нить А и нить B хотят выполнить AddOne (). но А начинается первой и считывает Bedeutung myInt (0) в TMP. Теперь по некоторым причинам планировщик решает остановить поток А и отложить выполнение нити B. Поток В настоящее время также считывает Bedeutung myInt (0) в его собственной переменной TMP. Нить B завершает весь метод так, что в конце концов myInt = 1. И 1 возвращается. Поток А продолжается. И добавляет 1 к TMP (TMP 0 для нити A). А затем сохраняет это Bedeutung в myInt. myInt снова 1.

    So in this case the method AddOne was called two times, but because the method was not implemented in a thread safe way the value of myInt is not 2, as expected, but 1 because the second thread read the variable myInt before the first thread finished updating it.

    Так что в этом случае метод AddOne был вызван два раза, но так Wie этот метод не был реализован в потоке безопасным способом величина myInt не 2, Wie ожидалось, а 1, потому что второй поток чтения переменной myInt закончился перед первой нитью до его обновления.

    Creating thread safe methods is very hard in non trivial cases. And there are quite a few techniques. In Java you can mark a method as synchronized, this means that only one thread can execute that method at a given time. The other threads wait in line. This makes a method thread safe, but if there is a lot of work to be done in a method, then this wastes a lot of time. Another technique is to 'mark only a small part of a method as synchronized' by creating a lock or semaphore, and locking this small part (usually called the critical section). There are even some methods that are implemented as lockless thread safe, which means that they are built in such a way that multiple threads can race through them at the same time without ever causing problems, this can be the case when a method only executes one atomic call. Atomic calls are calls that can't be interrupted and can only be done by one thread at a time.

    Schaffung потоко-безопасных методов очень трудно. В Java вы можете пометить метод Wie синхронизированный, это будет означать, что только один поток может выполнить этот метод в данный момент времени. Другие нити, будут ждать в очереди. Это делает метод потоко-безопасным, но если много работы предстоит сделать в методе, то на это будет уходить много времени. Другой метод заключается в разметке лишь малой части метода, Wie синхронизированного 'путем создания локов(locks) oder семафоров, и запирании этой небольшой части (обычно называемый критический раздел (critical section)). Есть даже некоторые методы, которые реализуются Wie беззамочные потокобезопасные (lockless thread safe), это означает, что они построены таким образом, что несколько потоков могут проходить через них в одно время и никогда не вызывают проблем, это может быть в случае, когда метод выполняет только один атомарный вызов. Атомарные вызовы это вызовы, которые не могут быть прерваны, и может быть реализованы только одним потоком.

  9. Was такое "happens-before"?

    Есть статья на википедии, она не конкретно про "happens-before", но все – таки.

    А так-то:
    «Выполняется прежде» (англ. happens before) — отношение строгого частичного порядка (арефлексивное, антисимметричное, транзитивное), введённое между атомарными командами (++ и -- не атомарны!), придуманное Лесли Лэмпортом и не означающее «физически прежде». Оно значит, что вторая команда будет «в курсе» изменений, проведённых первой.

    Модель памяти Java

    В частности, одно выполняется прежде другого для таких операций (список не исчерпывающий):

    • Синхронизация и мониторы:
    • Захват монитора (начало synchronized, метод lock) и всё, что после него в том же потоке.
    • Возврат монитора (конец synchronized, метод unlock) и всё, что перед ним в том же потоке.
    • Таким образом, оптимизатор может заносить строки в синхроблок, но не наружу.
    • Возврат монитора и последующий захват другим потоком.
    • Запись и чтение:
    • Любые зависимости по данным (то есть запись в любую переменную и последующее чтение её же) в одном потоке.
    • Всё, что в том же потоке перед записью в volatile-переменную, и сама запись.
    • volatile-чтение и всё, что после него в том же потоке.
    • Запись в volatile-переменную и последующее считывание её же.[4][2] Таким образом, volatile-запись делает с памятью то же, что возврат монитора, а чтение — то же, что захват.[5] А значит: если один поток записал в volatile-переменную, а второй обнаружил это, всё, что предшествует записи, выполняется раньше всего, что идёт после чтения; см. иллюстрацию.
    • Для ein Objektных переменных (например, volatile List x;) столь сильные гарантии выполняются для ссылки на ein Objekt, но не для его содержимого.
    • Обслуживание ein Objektа:
    • Статическая инициализация и любые действия с любыми экземплярами ein Objektов.
    • Запись в final-поля в конструкторе[6] и всё, что после конструктора. Как исключение из всеобщей транзитивности, это соотношение happens-before не соединяется транзитивно с другими правилами и поэтому может вызвать межпоточную гонку.[7]
    • Любая работа с ein Objektом и finalize().
    • Обслуживание потока:
    • Запуск потока и любой Code в потоке.
    • Зануление переменных, относящихся к потоку, и любой Code в потоке.
    • Код в потоке и join(); Code в потоке и isAlive() == false.
    • interrupt() потока и обнаружение факта останова.
  10. Was такое JMM?

    Java Memory Model

    Вот Verknüpfung: Chapter 17. Threads and Locks

    И вот выдержка из нее:

    A memory model describes, given a program and an execution trace of that program, whether the execution trace is a legal execution of the program. The Java programming language memory model works by examining each read in an execution trace and checking that the write observed by that read is valid according to certain rules.

    Я понял на своем уровне что это набор правил:

    Правило № 1: однопоточные программы исполняются псевдопоследовательно. Это значит: в реальности процессор может выполнять несколько операций за такт, заодно изменив их порядок, однако все зависимости по данным остаются, так что поведение не отличается от последовательного. Правило № 2: нет невесть откуда взявшихся значений. Чтение любой переменной (кроме не-volatile long и double, для которых это правило может не выполняться) выдаст либо Bedeutung по умолчанию (ноль), либо что-то, записанное туда другой командой.br /> И правило № 3: остальные события выполняются по порядку, если связаны отношением строгого частичного порядка «выполняется прежде» (англ. happens before).

  11. Какое исключение вылетит, если вызвать wait не в блоке synchronized?

    Вот Verknüpfung: Ответы на вопросы на собеседование Multithreading (часть 2)

    Основная причина вызова wait и notify из статического блока oder метода в том, что Java API обязательно требует этого. Если вы вызовете их не из синхронизированного блока, ваш Code выбросит IllegalMonitorStateException. Более хитрая причина в том, чтобы избежать состояния гонки между вызовами wait и notify.

Kommentare
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION