This article is a graduate school when the entrance to write, today when finishing the draft was dug out by me. At that time confused interview, wrote down some concurrent interview questions, many have not yet answered. Up to now, I have also learned a lot of concurrent knowledge. Looking back at these questions and the answers sorted out at that time, they are full of loopholes and very ridiculous. Post it as a reminder that if you don’t keep improving, you won’t see yourself as the idiot you were.


One of the most common phrases I heard when interviewing Java development interns was:

How can you do Java without learning concurrency?

Yes, it took a lot of disdain from my interviewers to realize the importance of Java concurrent programming in the Java language.

Concurrency model

Pessimistic lock and optimistic lock understanding and how to achieve, what are the implementation methods?

Pessimistic locking

Pessimistic locking assumes the worst (if you leave the door unlocked, troublemakers will break in and make a mess) and can only be performed if you ensure that other threads won’t interfere (by obtaining the correct lock).

Common implementations such as exclusive locks.

Higher security, but less efficient at low to medium concurrency.

Optimistic locking

Optimistic locks use collision checking to determine if there is interference from other threads during the update process. If there is, the operation will fail and can be retried (or not).

Common implementations such as CAS.

Partial optimistic locking reduces consistency, but efficiency is greatly improved at low to medium concurrency levels.

Concurrent programming

How do you create a thread in Java

From the aspect interface perspective, there is really only one way to implement the Runable interface; The Thread class, however, provides more support for threading operations, so it is common practice to implement the Runable interface, instantiate and pass in the Constructor of the Thread class.

  1. Inheriting Thread overrides the run method
  2. Implement Runable interface, overwrite the run method

How is Vector (HashTable) thread safe

Each method is decorated with the synchronized keyword.

The following problems are derived from the keyword synchronized.

How synchronized modifiers differ from code blocks

Different objects hold locks:

  1. When modifying methods: The current instance of this reference holds the lock
  2. When modifying a block of code: To specify an object that holds the lock

Thus, they have different meanings:

  1. A synchronized block of code may have a smaller scope of locking than a synchronized method, and generally the scope of locking is inversely proportional to performance.
  2. The modifier block can choose which object to lock, but the modifier can only lock this object.

How is ConcurrentHashMap thread safe

The thread-safe implementation of ConcurrentHashMap is different from that of HashTable:

  1. ConcurrentHashMap can be understood as not holding a HashMao directly, but replacing a HashMap with multiple segments. However, the Map part of the actual implementation is basically the same as the principle of HashMap. Modulo is taken to determine the segment to which table[I] belongs, so as to obtain different segment locks for different segments.
  2. Each Segment holds a lock, which not only achieves thread safety, but also takes into account performance

What are the methods of concurrent programming in Java

To start with the simplest answer, the industry is most commonly used is the focus, creative at the end.

  1. The synchronized keyword
  2. Use the wait, notify, and notifyAll methods inherited from the Object class
  3. Using thread-safe apis and collection classes:
    1. Use thread-safe collection classes such as Vector and HashTable
    2. Use weakly consistent collection classes such as ConcurrentHashMap, CopyOnWriteArrayList, and ConcurrentLinkedQueue provided in the Concurrent package
    3. There are several static methods in the Collections class that can get Collections that were unsynchronized by encapsulating them with synchronous methods, such asList list = Collection.synchronizedList(new ArrayList()).
    4. Use atomic variables, volatile variables, and so on
  4. Use the Semaphore, Latch, Barrier, Exchanger, Callable&Future, BlockingQueue, etc provided by the Concurrent package.
  5. Use Lock manually for lock-based concurrency control
  6. Manually implement conditional queue-based concurrency control using Condition or AQS
  7. Use CAS and SPIN for non-blocking concurrency control
  8. Using immutable classes
  9. Other concurrency models are not covered

Thus, the following problems arise:

Implementation principle of ConcurrentHashMap (see previous)

When does the copy operation of CopyOnWriteArrayList occur

The difference between synchronizedList&Vector

  1. In synchronizedList, the synchronized keyword modifies code blocks; The implementation of Vector decorates methods.
  2. The synchronizedList encapsulates the add, get, and remove code blocks. The Iterator is not synchronized. Iterator is also locked in the Vector.
  3. SynchronizedList encapsulates all List implementation classes as a synchronous collection. It still holds the List implementation class (ArrayList/LinkedList), so there is almost no difference between this implementation class and Vector except synchronization.

How synchronized modifiers differ from code blocks (see previous)

Semaphore, Latch, Barrier, switch

Non-recovery, Callable&Future, BlockingQueue implementation principle. Non – recovery, Callable&Future, BlockingQueue

The insertion algorithm of ConcurrentLinkedQueue

The core of the algorithm can be summarized as two steps:

  1. Check for intermediate state (SPIN)
  2. Try the CAS insert again

Details to be added.

Reference:

  • CopyOnWriteArrayList and Collections. SynchronizedList performance contrast
  • Difference between SynchronizedList and Vector

What is the difference between wait and sleep in Java?

The big difference is that while wait releases the lock, sleep holds it all the time. Wait is usually used for interthread interactions, and sleep is usually used to pause execution.

Why are wait, notify, and notifyAll not in thread?

The main reason is that JAVA provides locks at the object level rather than the thread level. Each object has a lock, which is acquired by the thread. Because wait, notify, and notifyAll are lock-level operations, we define them in the Object class because locks belong to objects.

Why are wait and notify called in synchronous blocks?

Java API forced to do so, if you don’t do this, your code will be thrown IllegalMonitorStateException anomalies. Another reason is to avoid race conditions between WAIT and notify.

Why should you check the wait condition in a loop?

Threads in the wait state may receive error alerts and pseudo-awakenings, and if the wait condition is not checked in the loop, the program will exit without meeting the end condition.

What is the difference between submit() and execute() methods in Java thread pools?

Both methods can submit tasks to a thread pool. The execute() method returns void, which is defined in the Executor interface, and the Submit () method returns a Future object that holds the results of the computation, which is defined in the ExecutorService interface. It expanded the Executor interface, other thread pool class like ThreadPoolExecutor and ScheduledThreadPoolExecutor has these methods.

What is the difference between volatile variables and atomic variables?

Volatile variables ensure antecedence, that is, that writes occur before subsequent reads, but they do not guarantee atomicity. For example, if the count variable is volatile, the count++ operation is not atomic. The AtomicInteger class provides an atomic method to make this operation atomic. For example, the getAndIncrement() method increments the current value atomically, and other data types and reference variables can perform similar operations.

Why are the Thread class’s sleep() and yield () methods static?

The Sleep () and yield() methods of the Thread class will run on the Thread currently executing. So it doesn’t make sense to call these methods on other threads that are in the wait state. That’s why these methods are static. They work in the currently executing thread and prevent programmers from making the mistake of thinking they can be called in another non-running thread.


This article is published under the Creative Commons Attribution – Share Alike 4.0 International License. All attribution and links to this article must be reserved.