376 lines
14 KiB
Markdown
376 lines
14 KiB
Markdown
## What is the difference between the **Ready to Run** and **Running** states?
|
|
|
|
---
|
|
|
|
🚦
|
|
|
|
- **Ready to Run**: The thread is in the Runnable pool and waiting for a processor to become available.
|
|
- **Running**: The thread's code is actively being executed by a processor.
|
|
%%%
|
|
How many threads can be in the **Running** state at any given time?
|
|
|
|
---
|
|
|
|
💻
|
|
|
|
- On a **single-processor** computer: At most **one** thread.
|
|
- On a **multi-processor** computer: At most **one thread per processor**.
|
|
%%%
|
|
|
|
## What operation moves a thread from the **Born** state to the **Runnable** state?
|
|
|
|
---
|
|
|
|
🐣 Invoking the **`start()`** method.
|
|
%%%
|
|
Define the following transitions between **Ready to Run** and **Running**:
|
|
|
|
1. **Dispatched**
|
|
2. **Yield**
|
|
3. **Preempted / Timeslice Expired**
|
|
|
|
---
|
|
|
|
🔄
|
|
|
|
1. **Dispatched**: The scheduler selects a "Ready" thread to start running.
|
|
2. **Yield**: The thread voluntarily gives up the processor to let others run.
|
|
3. **Preempted**: The OS forces the thread to stop running (often because its time is up or a higher priority thread arrived).
|
|
%%%
|
|
What does it mean to model a thread's lifecycle as a **Finite State Machine (FSM)**?
|
|
|
|
---
|
|
|
|
🤖 It means representing the various **states** a thread can occupy and the specific **operations** (transitions) that cause it to move from one state to another.
|
|
%%%
|
|
|
|
## When does a thread transition into the **Dead** state?
|
|
|
|
💀 When its **`run()` method terminates**, either by returning normally or by throwing an **uncaught exception**.
|
|
%%%
|
|
What causes a thread to move into the **Sleeping** state, and how does it leave?
|
|
|
|
---
|
|
|
|
😴
|
|
|
|
- **Entering**: The thread invokes the **`sleep()`** method.
|
|
- **Leaving**: It remains blocked until the specified **sleep time elapses** or it is interrupted.
|
|
%%%
|
|
|
|
## How do the **`wait()`** and **`notify()`** methods interact?
|
|
|
|
---
|
|
|
|
🛑
|
|
|
|
- **`wait()`**: Causes the current thread to block and enter the **Waiting** state.
|
|
- **`notify()` / `notifyAll()`**: Invoked by _another_ thread to move the waiting thread(s) back to the **Runnable** state.
|
|
%%%
|
|
What happens to a thread's state during an **I/O operation** (like reading a file)?
|
|
|
|
---
|
|
|
|
📥 The thread enters the **I/O blocked** state when the request is made and only becomes **Runnable** again once the **I/O is completed**.
|
|
%%%
|
|
|
|
## If a method call (like `sleep` or `wait`) causes a thread to relinquish the processor, when does that method **return**?
|
|
|
|
---
|
|
|
|
⏳ The method does **not return** until the thread is rescheduled and is back in the **Running** state.
|
|
%%%
|
|
In what **context** are methods always executed?
|
|
|
|
---
|
|
|
|
🧵 Methods are always executed in the **invoking thread's context**. A thread can only invoke a method when it is currently in the **Running** state.
|
|
%%%
|
|
|
|
## What are the three **named priority constants** defined in the Java Thread class?
|
|
|
|
---
|
|
|
|
1. **`Thread.MAX_PRIORITY`** (Value: 10)
|
|
2. **`Thread.NORM_PRIORITY`** (Value: 5)
|
|
3. **`Thread.MIN_PRIORITY`** (Value: 1)
|
|
%%%
|
|
What is the valid **integer range** for a thread's priority?
|
|
|
|
---
|
|
|
|
🔢 It must be an integer between **1 and 10**, inclusive.
|
|
%%%
|
|
How is a **newly created thread's** priority determined by default?
|
|
|
|
---
|
|
|
|
👪 It is set equal to the **priority of the thread that created it**.
|
|
%%%
|
|
Which methods are used to **modify or check** a thread's priority at runtime?
|
|
|
|
---
|
|
|
|
🛠️
|
|
|
|
- **`setPriority(int)`**: Sets the priority to a specific value.
|
|
- **`getPriority()`**: Returns the current priority of the thread.
|
|
%%%
|
|
|
|
## In a standard priority-based scheduler, which threads are **normally selected** to enter the Running state?
|
|
|
|
---
|
|
|
|
🚀 The threads in the **Runnable state with the highest priorities**.
|
|
%%%
|
|
|
|
## What are three ways a thread **voluntarily** relinquishes the processor?
|
|
|
|
---
|
|
|
|
🙋
|
|
|
|
1. **`Thread.yield()`**: Explicitly giving up the processor.
|
|
2. **`Thread.sleep()`**: Ceasing execution for a specific time.
|
|
3. **`Object.wait()`**: Waiting for a notification from another thread.
|
|
%%%
|
|
What two events cause a thread to **terminate** and release the processor permanently?
|
|
|
|
---
|
|
|
|
🏁
|
|
|
|
1. The **`run()`** method finishes its execution.
|
|
2. An **exception** is thrown that propagates beyond the `run()` method.
|
|
%%%
|
|
What is **Preemptive, Priority-Based Scheduling**?
|
|
|
|
---
|
|
|
|
🥊 A scheduling policy where a lower-priority thread is **forced to stop running** (preempted) as soon as a higher-priority thread becomes **ready to run**.
|
|
|
|
%%%
|
|
How does a **timeslice** affect thread execution in supported systems?
|
|
|
|
---
|
|
|
|
⏳ If timeslicing is supported, a thread will relinquish the processor if its allotted **time interval (timeslice) expires**, allowing other threads of equal priority a chance to run.
|
|
%%%
|
|
Why does the JVM rely on the **preemption** of lower-priority threads?
|
|
|
|
---
|
|
|
|
🚨 To ensure that **high-priority threads** that need processor time urgently (e.g., for real-time tasks) receive it immediately without waiting for others to finish.
|
|
%%%
|
|
|
|
## In a JVM without **timeslicing**, how do two equal-priority threads ($t_1$ and $t_2$) share a single processor?
|
|
|
|
---
|
|
|
|
🧵 $t_1$ will run until it **terminates, relinquishes the processor voluntarily, or is preempted** by a higher-priority thread. $t_2$ will not start until $t_1$ is no longer eligible to run.
|
|
%%%
|
|
How does **Timeslicing** change the execution of equal-priority threads?
|
|
|
|
---
|
|
|
|
🔄 The scheduler uses a **Round-Robin** approach, allowing each thread to run for a **fixed amount of time** before switching to the next thread of the same priority.
|
|
%%%
|
|
Does the Java specification **require** timeslicing for equal-priority threads?
|
|
|
|
---
|
|
|
|
📜 **No.** Either approach (running to completion or timeslicing) is permitted by the Java specification.
|
|
%%%
|
|
If $t_1$ and $t_2$ are high priority and $t_3$ is low priority, when will $t_3$ get to run in a timesliced system?
|
|
|
|
---
|
|
|
|
⏳ Only when **both $t_1$ and $t_2$** are no longer eligible to run (e.g., they terminate or block). The JVM will not schedule lower-priority threads while higher ones are Runnable.
|
|
%%%
|
|
|
|
## What is **Bounded Priority Inversion**?
|
|
|
|
---
|
|
|
|
📉 It occurs when a **high-priority** thread is forced to wait for a **low-priority** thread to release a lock. It is "bounded" because the delay is limited to the time it takes the low-priority thread to finish its critical section.
|
|
%%%
|
|
|
|
## How does **Unbounded Priority Inversion** differ from the bounded version?
|
|
|
|
---
|
|
|
|
🌪️ It happens when a **medium-priority** thread preempts the low-priority thread that holds the lock. Since the high-priority thread is waiting for the lock, and the low-priority thread can't run to release it because of the medium thread, the high-priority thread is blocked for an **indeterminate (unbounded)** amount of time.
|
|
%%%
|
|
|
|
## Why is **disabling preemption** while a low-priority thread is in a critical section considered a poor solution?
|
|
|
|
🚫 Because it stops **all** other high-priority threads from running, even those that have **nothing to do** with the critical section or the lock in question.
|
|
%%%
|
|
What are the two common protocols used to solve the Priority Inversion problem?
|
|
|
|
---
|
|
|
|
🛡️
|
|
|
|
1. **Priority Inheritance Protocol**: The low-priority thread "inherits" the high-priority of the thread it is blocking until it releases the lock.
|
|
2. **Priority Ceiling (Priority Protect) Protocol**: The priority of the thread holding the lock is elevated to a predefined "ceiling" value (the highest priority of any thread that might ever need that lock).
|
|
%%%
|
|
Which two system conditions must exist for **Unbounded Priority Inversion** to be a risk?
|
|
|
|
---
|
|
|
|
⚙️
|
|
|
|
1. **Priority-based preemptive scheduling**.
|
|
2. A mechanism for **locking/mutual exclusion** to protect critical sections.
|
|
%%%
|
|
|
|
## How does the **Priority Inheritance Protocol** protect against medium-priority threads?
|
|
|
|
---
|
|
|
|
🛡️ When a high-priority thread blocks on a lock held by a low-priority thread, the **low-priority thread's priority is raised** to match the high-priority thread. This prevents medium-priority threads from preempting it and causing unbounded delay.
|
|
%%%
|
|
|
|
## When is a thread's priority **restored** to its original value under the Priority Inheritance Protocol?
|
|
|
|
---
|
|
|
|
🔙 As soon as the thread **leaves the critical section** and releases the lock.
|
|
%%%
|
|
What determines the **current priority** of a thread holding a lock under Priority Inheritance?
|
|
|
|
---
|
|
|
|
📈 It is the **higher** of:
|
|
|
|
1. Its own assigned priority.
|
|
2. The priority of the **highest-priority thread** currently blocked and waiting for that same lock.
|
|
%%%
|
|
How does a **Deadlock** occur in a system with shared resources?
|
|
|
|
---
|
|
|
|
🔄 It arises when two or more threads are stuck in a circular wait: Thread A holds Resource 1 and waits for Resource 2, while Thread B holds Resource 2 and waits for Resource 1.
|
|
|
|
%%%
|
|
What is the difference between **Deadlock Detection** and **Deadlock Prevention**?
|
|
|
|
---
|
|
|
|
🔍
|
|
|
|
- **Detection**: Allowing deadlocks to happen but using tools (like watchdog timers or request graph analysis) to find and reset the system.
|
|
- **Prevention**: Using a strict policy, such as **requesting resources in the same order**, to ensure a deadlock can never physically occur.
|
|
%%%
|
|
Why is "requesting resources in the same order" considered a **Prevention** strategy?
|
|
|
|
---
|
|
|
|
📏 It removes the possibility of a **circular wait**. If everyone agrees to lock Resource A before Resource B, you can never have a situation where two threads are waiting on each other.
|
|
%%%
|
|
How does a **Watchdog Timer** help handle deadlocks?
|
|
|
|
---
|
|
|
|
🐕 It is a timer that must be reset periodically by the software; if a deadlock occurs and the software stops responding, the timer expires and **automatically resets the system**.
|
|
%%%
|
|
|
|
## What is the **Ceiling Priority** of a lock?
|
|
|
|
---
|
|
|
|
🔝 It is a priority assigned to a lock when it is created that is **at least as high** as the priority of the highest-priority thread that can ever acquire it.
|
|
%%%
|
|
How does the **Priority Ceiling Protocol** handle preemption?
|
|
|
|
---
|
|
|
|
🛡️ Only threads with a priority **higher than the current global ceiling priority** can preempt a thread that is executing within a critical section.
|
|
%%%
|
|
|
|
## How does PCP prevent **Deadlocks**?
|
|
|
|
---
|
|
|
|
🚫 By design, the protocol ensures the system is **deadlock-free** because it coordinates lock acquisition in a way that prevents circular wait conditions from ever forming.
|
|
%%%
|
|
In the Priority Ceiling Protocol, why might a high-priority thread be **blocked** even if a lock is free?
|
|
|
|
---
|
|
|
|
🚦 If the thread's priority is not higher than the **current global ceiling priority**, it is blocked from acquiring the lock to ensure that lower-priority threads currently holding other resources can finish without interference.
|
|
%%%
|
|
What are the main differences between **Priority Inheritance** and **Priority Ceiling** regarding configuration?
|
|
|
|
---
|
|
|
|
⚙️
|
|
|
|
- **Priority Inheritance**: Managed **transparently** by the system; no programmer setup is required.
|
|
- **Priority Ceiling**: Requires the **programmer to manually configure** the priority ceilings for every lock.
|
|
%%%
|
|
How do the two protocols differ in when they "promote" a thread's priority?
|
|
|
|
---
|
|
|
|
📈
|
|
|
|
- **Priority Inheritance**: Promotion occurs **only when** a higher-priority thread actually attempts to acquire the lock.
|
|
- **Priority Ceiling**: Promotion is associated with the **lock itself**; the priority is effectively managed as soon as any thread interacts with the protected critical section.
|
|
%%%
|
|
Does **Java** currently support the Priority Ceiling Protocol?
|
|
|
|
---
|
|
|
|
📜 **No.** The priority ceiling protocol is not currently supported by Java; Java implementations typically use Priority Inheritance.
|
|
%%%
|
|
|
|
## What are **Green Threads**?
|
|
|
|
---
|
|
|
|
🌳 A thread model where the **JVM is completely responsible** for thread management (stack, PC, bookkeeping). The underlying operating system is **unaware** of these threads.
|
|
%%%
|
|
How does the OS view a Java process using **Green Threads**?
|
|
|
|
---
|
|
|
|
👁️ The OS sees the entire JVM as a **single process** with a single thread. All context switching between Java threads happens internally within the JVM without OS system calls.
|
|
|
|
%%%
|
|
What are the scheduling characteristics of most **Green Thread** implementations?
|
|
|
|
---
|
|
|
|
⚖️ They typically support **priority-based, preemptive scheduling**, but most do **not** support timeslicing. They often use **priority inheritance** to prevent inversion.
|
|
%%%
|
|
What defines the **Native Threads** model?
|
|
|
|
---
|
|
|
|
🖥️ Java threads are mapped directly to the **threads supported by the host Operating System**. The OS, not the JVM, is responsible for scheduling the threads.
|
|
%%%
|
|
How are Java priorities handled in **Windows Native Threads**?
|
|
|
|
---
|
|
|
|
🗺️ There is a **one-to-one mapping** between Java and Win-32 threads, but because Windows has fewer priority levels, the **10 Java priorities are mapped onto 6 Win-32 priorities**.
|
|
%%%
|
|
Why might equal-priority threads behave differently on Windows vs. early Unix Green Threads?
|
|
|
|
---
|
|
|
|
⏳ In Windows Native Threads, equal-priority threads **timeslice**, whereas many Green Thread implementations do not support timeslicing (one runs until it blocks or terminates).
|
|
%%%
|
|
In **Embedded Systems**, how is Java thread scheduling typically determined?
|
|
|
|
---
|
|
|
|
📟 Java threads are usually mapped to the native threads/tasks of the **Real-Time Operating System (RTOS)**. Therefore, Java thread scheduling is equivalent to **RTOS scheduling**.
|
|
%%%
|
|
Why is **OS support (Native Threads)** required for true multi-processor concurrency?
|
|
|
|
---
|
|
|
|
🚀 Because Green Threads are managed inside a single OS process, they cannot be distributed across multiple physical CPUs by the OS. Only **Native Threads** allow the OS to run different Java threads on different cores simultaneously.
|