DefNeo
Level 36

Level 27

Published in the Random EN group
Level 27
  1. What is deadlock?

    A deadlock is a situation where two or more threads are blocked waiting for each other. Deadlock is also called deadlock.

    Deadlock is a situation in which two or more processes, occupying some resources, try to get some other resources occupied by other processes, and none of the processes can occupy the resource they need and, accordingly, free it.

    There are synchronization order deadlocks (resolved by assigning an order);

    Mutual blocking between objects (different objects try to access the same synchronized blocks);

    Resource deadlock (when trying to access some resources that only one thread can use at a time).

  2. What strategies do you know to prevent deadlocks?

    Of course, if the code is written without any errors, then there will be no deadlocks in it. But who can guarantee that his code is written without errors? Of course, testing helps to identify a significant part of the errors, but as we have seen earlier, errors in multithreaded code are not easy to diagnose, and even after testing, one cannot be sure that there are no deadlock situations. Can we somehow play it safe from blocking? The answer is yes. Similar techniques are used in database engines, which often need to recover from deadlocks (related to the mechanism of transactions in the database). The interface Lockand its implementations available in the package java.util.concurrent.locksallow you to try to occupy the monitor associated with an instance of this class by the method tryLock(returns true if the monitor was able to occupy the monitor).

    There is also a strategy for using open calls, that is, calling methods of other objects outside of the synchronized block.

    Link to the article: Mutual blocking (deadlock) in Java and methods of dealing with it

  3. Can deadlocks occur when using methods wait-notify?

    It is difficult for me personally to answer this question, but after reading various discussions on this topic on the Internet, we can say the following:

    Deadlocks can be avoided through the judicious use of synchronized, volatile, monitor ( wait(), notify(), notifyAll()), and if you dig deeper, then using classes java.utils.concurrent: instead of ordinary collections - multi-threaded options ( ConcurrentHashMap, for example); if you need a more complex way to synchronize threads - various CyclicBarrier, CountDownLatch.

    If you use it correctly wait- notify, then deadlocks should not arise.)))

    Here is the link: Mutual blocking or Deadlock.

  4. Which is more commonly used: notifyor notifyAll?

    The java.lang.Object.notify() wakes up a single thread that is waiting on this object's monitor. If any threads are waiting on this object, one of them is chosen to be awakened. The choice is arbitrary and occurs at the discretion of the implementation. A thread waits on an object's monitor by calling one of the wait methods.

    This method should only be called by a thread that is the owner of this object's monitor. A thread becomes the owner of the object's monitor in one of three ways:

    • By executing a synchronized instance method of that object.
    • By executing the body of a synchronized statement that synchronizes on the object.
    • For objects of type Class, by executing a synchronized static method of that class.

    Only one thread at a time can own an object's monitor.

    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.

    The awakened threads will not be able to proceed until the current thread relinquishes the lock on this object. the awakened threads will compete in the usual manner with any other threads that might be actively competing to synchronize on this object; for example, the awakened threads enjoy no reliable privilege or disadvantage in being the next thread to lock this object.

    This method should only be called by a thread that is the owner of this object's monitor.

    These are excerpts from the documentation. The question is mostly rhetorical, depending on which application, depending on the situation))) I don’t even know how I would answer. If someone has any guesses, then please leave in the comments, I will be very glad to read.

  5. The method waitis recommended to be used with constructions ifor while?

    Here I will answer simply with a quote from the site: Thread Synchronization

    Regarding the method call wait. This is already from the category of pure technology. It is recommended to call waitfrom inside the loop while. That is, do not write

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

    ..., A

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

    Why is it necessary. The thing is, notifyanyone can call. Just by mistake, from which no one is immune. In the case of the experience I described above, we undertook the rework precisely in order to avoid this possibility. We just hid the object on which the synchronization takes place. And only our code had access to it. This is good practice, but not always possible, unfortunately. So, if the thread is waiting for some condition to be met, option c is more whilereliable. If the thread was started by mistake, it will check the condition again and, if necessary, will wait further.

    In addition, the possibility of a simple exit from waiting without calling is not excluded notify. I honestly admit that I did not see this in the virtual machine specification, although I specifically looked for it. But some "gurus" claim that the VM can exit the wait state spontaneously. And what's more, it happens from time to time. If someone gives a link to the relevant specification - I will be grateful!

  6. What happens after the method is called 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.

    Wakes up all threads that were waiting on this monitor.

  7. What benefits does the object get if it immutable?

    Found a comment on: immutable objects and multithreading

    ImmutableAn object is an object whose state, once created, cannot be changed. In the case of Java, this means that all instance fields of a class are marked as finalbeing primitives or also immutabletypes.

    Example:

    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;
        }
    }

    Once an instance has been created, ImmutablePointit cannot be modified.

    The simplest example immutableof a class from the JDK is String. Any methods you call on a string (like description.toLowerCase()) will return a new string, not modify the original string.

    An example mutableclass from the JDK is Date. For example myDate.setHours(x)modifies the instance itself myDate!

    There is a difference between immutable-object (that is, immutable) and final-reference.

    The keyword finalfor object types ensures that only the reference is immutable, not the object itself. For example, if you have finala -reference to ArrayList<T>, you can still add new elements to it or modify existing ones.

    In the case of immutable-object, the object does not change at all after the end of the constructor. A modifier alone finalis not enough for this, it is necessary that all subobjects are also immutable. In principle, you can keep a reference to a mutable object inside, but treat it in such a way that it does not change.

    There are many benefits to using immutable objects. For example, such an object is much easier to judge in a situation where many parts of the program have a reference to it (for a mutable object, any part of the program can call the mutating function at almost any time and from any thread).

    But what is important for us in the context of the question is that immutable objects do not require synchronization during multi-threaded access. That's actually the whole recommendation: use immutable objects, and you don't have to think about what needs to be and what doesn't need to be synchronized. The only possible problem is if you publish a reference to an object inside a constructor that has not yet been executed, through which someone else can access it and see the object in a changing state! (This is not uncommon. For example, sometimes a programmer wants to add an object in a constructor to the collection of all objects of a given type.)


    A distinction must be made between objects that are truly immutable and objects that only have a read-only interface. While reading, an object can still change its internal structure (for example, cache the most recent request for data). Such objects are not strictly immutable, and cannot be used from different threads without precautions. (So ​​if your object includes other objects, make sure the documentation guarantees they are immutable!)


    Note that for immutable object fields, you are practically required to use final! The point is the so-called safe publication. See. Instructions in a Java program can be rearranged by both the optimizer and the processor (Java has a rather weak memory model). Therefore, if no special action is taken, the end of the constructor and the assignment of values ​​to the fields can be rearranged (but not visible within the current thread)! Use finalensures that this does not happen.

    In the case of multi-threaded programming, the advantages immutableof classes are obvious: once created, objects can be passed to other threads and they will always be up to date. Those. you don't have to check if your instance's state is stale or modified by another thread while you're working with it. For example, you have a method bill(Date endDate), in which you naively check for compliance endDatewith some preconditions and start working with it. At this point, another thread might change endDate, such as setting it deep into the past. The consequences can be the most amazing.

  8. What is thread-safe?

    Again: 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 occurring.

    The thread-safe state implies that a method or class can be used by multiple threads without collision problems, i.e. deadlocks.

    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.

    Here both thread A and thread B want to execute AddOne (). but A starts first and reads the value of myInt (0) into TMP. Now, for some reason, the scheduler decides to stop Thread A and defer Thread B. Thread Currently also reads the value myInt (0) in its own TMP variable. Thread B completes the entire method so that eventually myInt = 1. And 1 is returned. Stream A continues. And adds 1 to TMP (TMP 0 for thread A). And then stores this value in myInt. myInt is again 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.

    So in this case the method AddOnewas called twice, but because this method was not implemented in a thread-safe way, the value of myInt is not 2 as expected, but 1, because the second thread reading the variable myIntended before the first thread before updating it.

    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.

    Making methods thread-safe is very difficult. In Java, you can mark a method as synchronized, which means that only one thread can execute that method at a given time. Other threads will wait in line. This makes the method thread-safe, but if there is a lot of work to be done in the method, it will take a lot of time. Another method is to mark only a small part of the method as synchronized by creating locks or semaphores, and locking this small part (commonly called a 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 go through them at the same time and never cause problems, this can be the case, when the method makes only one atomic call. Atomic calls are calls that cannot be interrupted and can only be implemented by a single thread.

  9. What is "happens-before"?

    There is an article on Wikipedia, it is not specifically about "happens-before", but still.

    And so:
    “It happens before” (eng. happens before) is a strict partial order relation (areflexive, antisymmetric, transitive), introduced between atomic commands ( ++and --not atomic!), invented by Leslie Lamport and does not mean “physically before”. It means that the second team will be "in the know" of the changes made by the first.

    Java memory model

    In particular, one is performed before the other for such operations (the list is not exhaustive):

    • Synchronization and monitors:
    • Capturing the monitor (beginning synchronized, method lock) and everything after it in the same thread.
    • Returning the monitor ( end synchronized, method unlock) and everything before it on the same thread.
    • Thus, the optimizer can push rows into the sync block, but not out.
    • Returning the monitor and then capturing it by another thread.
    • Writing and reading:
    • Any data dependencies (that is, writing to any variable and then reading it) in one thread.
    • Everything in the same stream before writing to volatilethe -variable, and the writing itself.
    • volatile-reading and everything after it in the same stream.
    • Writing to volatile-variable and then reading it.[4][2] Thus, volatilea -write does to memory what a monitor return does, and a read does what a capture does.[5] This means: if one thread has written to volatilea -variable, and the second one has detected it, everything that precedes the write is executed before everything that comes after the read; see illustration.
    • For object variables (for example, volatile List x;) such strong guarantees hold for the object reference, but not for its contents.
    • Object maintenance:
    • Static initialization and any actions with any instances of objects.
    • Writing to final-fields in the constructor[6] and everything after the constructor. As an exception to general transitivity, this happens-before relation does not connect transitively with other rules and can therefore cause a cross-thread race.[7]
    • Any work with the object and finalize().
    • Stream service:
    • Starting a thread and any code in the thread.
    • Zeroing variables related to the thread and any code in the thread.
    • Code in flow and join();code in flow and isAlive() == false.
    • interrupt()flow and stop detection.
  10. What is JMM?

    Java Memory Model

    Here is the link: Chapter 17. Threads and Locks

    And here is an excerpt from it:

    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.

    I understood at my level that this is a set of rules:

    Rule #1: Single-threaded programs run pseudo-sequentially. This means: in reality, the processor can perform several operations per clock, at the same time changing their order, however, all data dependencies remain, so the behavior does not differ from sequential. Rule number 2: there are no out of nowhere values. Reading any variable (except non-volatile longs and doubles, for which this rule may fail) will return either the default value (zero) or something written there by another command. br /> And rule #3: the rest of the events are executed in order if they are related by a strict partial order “happens before” relation.

  11. What exception will be thrown if called waitoutside of a block synchronized?

    Here is the link: Multithreading Interview Questions Answered (Part 2)

    The main reason for calling waitand notifyfrom a static block or method is that the Java API necessarily requires it. If you call them from a non-synchronized block, your code will throw IllegalMonitorStateException. A trickier reason is to avoid a race condition between calls to waitand notify.

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