Lenovo Backend Interview Secrets: Deadlocks, DNS, TLS & Java ArrayList

The article examines Lenovo’s 2023 graduate hiring salaries across cities, roles, and education levels, then shares a recent backend interview experience, detailing questions on deadlocks, networking layers, DNS resolution, TLS handshakes, common data structures, and Java’s ArrayList implementation, offering practical insights and recommendations.

IT Services Circle
IT Services Circle
IT Services Circle
Lenovo Backend Interview Secrets: Deadlocks, DNS, TLS & Java ArrayList

Lenovo Backend Interview (First Round)

1. Deadlock and its causes

A deadlock occurs only when the following four conditions are simultaneously satisfied:

Mutual exclusion : multiple threads cannot use the same resource at the same time.

Hold and wait : a thread holding one resource requests another resource while still holding the first.

No preemption : a resource cannot be forcibly taken from a thread until the thread releases it voluntarily.

Circular wait : the waiting threads form a circular chain of resource requests.

2. How to avoid deadlock

The simplest way is to break any one of the four conditions. The most practical technique is resource ordering , which eliminates the circular‑wait condition by enforcing a consistent acquisition order for all threads.

3. IP protocol layer

The IP protocol belongs to the Network layer of the OSI/TCP‑IP model.

4. Protocol for domain name to IP translation

Domain names are translated to IP addresses using the DNS (Domain Name System) protocol.

5. DNS resolution process

The client sends a DNS query for www.server.com to the configured local DNS server.

If the local server’s cache contains the record, it returns the IP address; otherwise it queries the root DNS server.

The root server points the client to the .com top‑level DNS server.

The .com server returns the address of the authoritative DNS server for server.com.

The authoritative server looks up the exact record and returns the IP address to the local DNS server.

The local DNS server finally returns the IP address to the client, which can now connect to the target host.

6. Modifying the hosts file

The hosts file binds domain names to specific IP addresses locally, bypassing external DNS resolution. For example, adding the line 192.168.1.100 www.test.com lets a developer test a website before it is publicly deployed.

7. TLS handshake process (RSA‑based)

TLS First Handshake

ClientHello : client sends supported TLS version, a random number ( ClientRandom), and a list of cipher suites.

TLS Second Handshake

ServerHello : server replies with the selected TLS version, its own random number ( ServerRandom), the chosen cipher suite, and its digital certificate.

TLS Third Handshake

Client verifies the server certificate, extracts the server’s public key, encrypts a pre‑master secret with it, and sends the encrypted secret together with a “ChangeCipherSpec” notification.

TLS Fourth Handshake

Server decrypts the pre‑master secret, derives the session key, sends its own “ChangeCipherSpec” and “Finished” messages, completing the handshake. Subsequent communication uses the derived session key while the underlying protocol remains HTTP.

TLS handshake diagram
TLS handshake diagram

8. Common data structures (quick overview)

Array – contiguous memory, O(1) random access, O(n) insertion/deletion.

Linked list – nodes stored non‑contiguously, fast insertion/deletion, slower random access.

Stack – LIFO, only top‑element operations.

Queue – FIFO, enqueue at tail and dequeue at head.

Tree – hierarchical, suitable for representing nested relationships.

9. Java ArrayList

ArrayList

is a dynamic array implementation in the java.util package that implements the List interface. It stores elements in an internal Object[] array and automatically expands when capacity is exceeded.

Dynamic expansion : when the number of elements reaches the current capacity, the array grows (default new capacity = old capacity × 1.5). Initial capacity can be set explicitly via new ArrayList<>(initialCapacity).

Ordered and allows duplicates : elements are kept in insertion order and duplicate (including null) values are permitted.

Not thread‑safe : concurrent modifications can corrupt internal state; thread‑safe alternatives include Collections.synchronizedList or CopyOnWriteArrayList.

Fast random access : get(int index) runs in O(1); insertion/deletion (especially in the middle) requires shifting elements and runs in O(n).

10. ArrayList insertion process

ArrayList relies on two internal fields: size – current number of stored elements. capacity – length of the backing Object[] array.

Tail insertion ( add(E e) )

public boolean add(E e) {
    // Step 1: ensure there is room for size+1 elements
    ensureCapacityInternal(size + 1);
    // Step 2: store the element at the end and increment size
    elementData[size++] = e;
    return true;
}

Steps:

Call ensureCapacityInternal(size+1) to check whether the backing array needs to grow. If the array is null, a default capacity (10) is allocated; if size+1 exceeds the current length, a new array of size oldCapacity + (oldCapacity>>1) (≈1.5×) is created and the old elements are copied.

Assign the new element to elementData[size] and then increment size.

Insertion at a specific index ( add(int index, E element) )

public void add(int index, E element) {
    // Step 1: validate index
    if (index > size || index < 0) {
        throw new IndexOutOfBoundsException();
    }
    // Step 2: ensure capacity
    ensureCapacityInternal(size + 1);
    // Step 3: shift subsequent elements right by one position
    System.arraycopy(elementData, index, elementData, index + 1, size - index);
    // Step 4: insert the new element and update size
    elementData[index] = element;
    size++;
}

Steps:

Check that index is within 0..size (index == size is equivalent to tail insertion).

Perform the same capacity check as in tail insertion.

Use System.arraycopy to move the block elementData[index .. size‑1] one position to the right, creating a free slot at index.

Store the new element at elementData[index] and increment size.

11. Thread safety of ArrayList

ArrayList is not thread‑safe. All mutating methods operate on shared fields without synchronization, leading to race conditions such as: size++ is non‑atomic, causing lost updates or overwriting of elements.

Concurrent writes to elementData can corrupt the array.

The internal modCount may become inconsistent, triggering ConcurrentModificationException. size lacks the volatile modifier, so updates may not be visible across threads.

Example of a race during tail insertion:

// Thread A
ensureCapacityInternal(size + 1);
elementData[size++] = e1; // writes to slot 5

// Thread B (interleaved)
ensureCapacityInternal(size + 1);
elementData[size++] = e2; // also writes to slot 5

Possible outcomes:

One element overwrites the other, losing data.

If the array is already full, both threads may think there is space, leading to an ArrayIndexOutOfBoundsException.

To achieve thread safety, wrap the list with Collections.synchronizedList or use a concurrent implementation such as CopyOnWriteArrayList.

ArrayList concurrency illustration
ArrayList concurrency illustration
Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

JavaBackend DevelopmentinterviewData Structures
IT Services Circle
Written by

IT Services Circle

Delivering cutting-edge internet insights and practical learning resources. We're a passionate and principled IT media platform.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.