Anduril System Design Preparation

0.0(0)
Studied by 0 people
call kaiCall Kai
learnLearn
examPractice Test
spaced repetitionSpaced Repetition
heart puzzleMatch
flashcardsFlashcards
GameKnowt Play
Card Sorting

1/21

encourage image

There's no tags or description

Looks like no tags are added yet.

22 Terms

1
New cards

Threads and processes

A thread is an execution path within a process. Threads in the same process can share memory, which makes communication convenient but introduces synchronization problems. Separate processes generally have separate address spaces.

2
New cards

Concurrency vs. Parallelism

Concurrency is two lines of customers ordering from a single cashier (lines take turns ordering, overlapping progress); Parallelism is two lines of customers ordering from two cashiers (each line gets its own cashier, literally executing at the same time).
Concurrency issues stem from the fact that threads in the same process share memory.

3
New cards

Race condition

A race condition occurs when the result depends on the timing or interleaving of concurrent operations. Two threads read a counter with value 5, both add 1, and both write 6. The expected value of 7 is lost. This is a classic lost-update race.

4
New cards

Critical sections

A critical section is code that accesses shared state and may need protection.

5
New cards

Mutex

A mutex (mutual-exclusion lock) ensures that only one thread at a time can enter a protected critical section. Other threads trying to acquire that lock must wait until it becomes available.

Know when to lock, how to keep the critical section short, and how to avoid leaving a lock held after an error.

6
New cards

Semaphores

A semaphore maintains a count of available permits. A thread acquires a permit before proceeding and releases it afterward. This can limit how many threads access a resource simultaneously. They allow us to limit concurrent operations (e.g., before downloading, must get a permit), or limit aggregate consumption (e.g., each permit represents a unit of resource like 1 MB).

Use semaphores to limit concurrent operations, like when you can have at most 5 downloads or at most 10 API calls at a given time. This helps manage resource scarcity.

7
New cards

Structure of Interview

  1. Functional Requirements

  2. Non-functional requirements (Discuss latency, throughput, reliability, security, resource limits, and availability. For physical systems, clarify real-time deadlines, network connectivity, and what must keep working offline.)

  3. Core entities and state (Identify the important domain objects, their relationships, and their state. Examples might include a sensor, measurement, vehicle, track, mission, or command, depending on the prompt.)

  4. Interfaces/communication (Define how components communicate: important APIs, message types, inputs, outputs, and ownership. Don't automatically assume everything uses REST; internal communication might use queues, RPC, or direct in-process calls.)

  5. End to end data flow (input to output)

  6. High-Level Architecture (Draw the major components, their connections, and their responsibilities.)

  7. Deep Dives (Discuss concurrency, performance, hashing, estimation, failure handling, security, and alternatives wherever relevant.)


8
New cards

Atomics

Atomics provide thread-safe operations on single variables without locks. Under the hood, they use CPU instructions like compare-and-swap (CAS) that complete in one uninterruptible step.

Consider tracking how many seats have been booked. With a regular integer, incrementing is unsafe because increment operations are actually three steps (read, add, write) that can interleave. With an atomic integer, the increment happens as one indivisible operation. This pattern is called optimistic concurrency. You optimistically assume no one else will interfere, do your work, and only retry if that assumption was wrong. Under low contention most CAS attempts succeed on the first try, making this faster than acquiring a lock.

9
New cards

Condition Variables

Condition variables let threads wait efficiently for a condition to become true. A thread acquires a lock, checks a condition, and if not satisfied, waits. This atomically releases the lock and puts the thread to sleep. When another thread signals, waiters wake up and re-check.

10
New cards

Blocking Queues

Blocking queues combine a queue with condition variables to provide thread-safe producer-consumer handoff. Producers call put() to add items; if full, they block. Consumers call take() to remove items; if empty, they block.

11
New cards

Correctness

Correctness is about preventing data corruption when multiple threads access shared state. Two threads both book the same seat. A counter that should be 1000 reads 847. A bank balance missing deposits. The danger isn't deadlock or performance, it's silently producing wrong results.

12
New cards

Coarse-Grained Locking

When a thread acquires a lock, every other thread trying to acquire that same lock has to wait until the first thread releases it. Coarse-grained locking means using one lock to guard all booking operations. Every thread that wants to check or modify seat availability waits for the same lock.

13
New cards

Read-Write Lock

Sometimes your workload is heavily skewed toward reads. A read-write lock has two modes: read (shared) and write (exclusive). Multiple threads can hold the read lock simultaneously since they're just reading and can't corrupt each other's view. But the write lock is exclusive. When a thread wants to write, it waits for all readers to finish, then blocks everyone else until the write completes.

14
New cards

Fine-Grained Locking

Fine-grained locking uses multiple locks, where each lock protects a smaller piece of state. Instead of one lock for the entire venue, you have one lock per seat. Threads only block each other when they're competing for the same resource. It solves the issues that coarse-grained locking has at scale. To prevent deadlock, always acquire locks in a consistent order.

15
New cards

Coordination

Coordination is about threads communicating and handing off work. One thread produces tasks, another consumes them. A service sends a request, another service processes it.

16
New cards

Shared State Coordination

How do threads communicate and sequence their work? They need to signal each other ("work is ready"), wait efficiently without burning CPU, and handle the case where one side is faster than the other.
The most common approach to coordination uses shared data structures. Threads communicate by reading and writing to the same memory. A producer adds an item to a queue, a consumer removes it. The queue is the shared state, and synchronization primitives like locks and condition variables ensure threads don't step on each other.
Condition Variables allow workers to actually sleep when there's nothing to do, then wake up the instant work arrives. Blocking queues implement this for you.

17
New cards

Message Passing Coordination

Instead of multiple threads accessing shared data structures, what if each thread had its own private state and communicated only by sending messages?

This is the actor model. An actor is an independent unit of computation with three properties: it has a mailbox (a queue of incoming messages), it processes messages one at a time, and it can send messages to other actors.

18
New cards

Resource Pooling

Resource pooling is a solution to resource scarcity - specifically, when connection pools are scarce. When a thread needs a connection, it pulls from the blocking queue. If the queue is empty because all connections are checked out, the thread blocks. When another thread finishes, it returns the connection to the queue, waking one waiting thread. Semaphores cannot contain and dispense the actual connection objects, but a queue can. This is useful when you have objects that are expensive to create, but can be reused.

19
New cards

Deadlock, starvation, and livelock

  • Deadlock: Two threads wait forever for locks held by each other.

  • Starvation: A thread waits indefinitely because other threads keep getting the resource.

  • Livelock: Threads keep reacting to one another, but neither makes useful progress.


20
New cards

Backpressure, bounded queues, and overload

Solutions for when producers permanently outpace consumers.

A bounded queue prevents unlimited memory growth, but then you need a policy:

  • Block producers.

  • Reject new work.

  • Drop or coalesce obsolete updates when the domain permits it.

  • Add capacity or scale consumers if the bottleneck can be addressed that way.


21
New cards

time units

1 ns

Nanosecond

One-billionth of a second.

10^-9 seconds

1 μs

Microsecond

One-millionth of a second.

10^-6 seconds = 1,000 ns

1 ms

Millisecond

One-thousandth of a second.

10^-3 seconds = 1,000 μs

1 s

Second

One second.

1,000 ms

22
New cards