JNTU
JNTU B.Tech III CONCURRENT PROGRAMMING Previous Question Paper (February/March – 2022 - R18)
Answer any five questions. All questions carry equal marks.
Main
Describe the properties of program correctness.
Answer
JNTU
CONCURRENT PROGRAMMING
B.Tech, CSE, III-II, R18, May-2024 Exam
Instructions: Answer all questions.
A program is considered correct if it behaves as specified by its requirements. Program correctness is a fundamental concept in software engineering, especially critical in concurrent programming where the complexity of interactions between threads can lead to subtle errors. The properties of program correctness can be broadly categorized into several key aspects:
- Functional Correctness: This is the most basic property, ensuring that the program produces the correct output for all valid inputs and adheres to its specified functional requirements. For concurrent programs, this means that the final state and results are consistent, regardless of the interleaving of thread execution.
- Termination: A correct program should eventually terminate for all valid inputs, unless it is designed to run indefinitely (e.g., an operating system kernel). In concurrent systems, termination can be complex due to potential deadlocks or livelocks where threads may get stuck waiting for each other indefinitely.
- Robustness: A robust program can handle unexpected or erroneous inputs gracefully, without crashing or producing incorrect results. This includes error handling, exception management, and resilience to partial failures. In concurrent settings, robustness also pertains to handling race conditions and ensuring data integrity even under stress.
- Efficiency: While not strictly a correctness property in the sense of producing wrong results, efficiency (time and space complexity) is often a practical requirement. A program that is functionally correct but takes an unacceptably long time or consumes excessive resources is often considered incorrect in a practical context. In concurrent systems, efficiency is often improved through parallelism, but incorrect synchronization can negate these gains or even degrade performance.
- Safety: In concurrent systems, safety properties ensure that 'nothing bad happens'. Examples include:
- Absence of Deadlock: A state where two or more processes are unable to proceed because each is waiting for the other to release a resource.
- Absence of Livelock: A state where processes are not deadlocked but are still unable to make progress because they are continuously changing their state in response to each other's actions.
- Absence of Starvation: A situation where a process is perpetually denied necessary resources to progress.
- Data Integrity: Ensuring that shared data structures remain in a consistent state and are not corrupted by concurrent access.
- Liveness: Liveness properties ensure that 'something good eventually happens'. Examples include:
- Progress: Every thread eventually makes progress towards completing its task.
- Fairness: Ensuring that all threads get a fair share of system resources, preventing starvation.
Achieving these properties in concurrent programs requires careful design, meticulous implementation, and rigorous testing, often involving techniques like formal verification, static analysis, and specific synchronization primitives.
Illustrate the concept of shared objects and synchronization between concurrent threads for prime number generation modules.
Answer
JNTU
CONCURRENT PROGRAMMING
B.Tech, CSE, III-II, R18, May-2024 Exam
Instructions: Answer all questions.
In concurrent programming, shared objects are data items or resources that can be accessed and potentially modified by multiple threads simultaneously. When multiple threads access and modify shared objects without proper coordination, it can lead to race conditions, where the outcome of the computation depends on the unpredictable timing of thread execution, resulting in incorrect program behavior. Synchronization mechanisms are crucial to manage concurrent access to shared objects, ensuring that operations are performed in a controlled and predictable manner.
Consider a scenario where multiple threads are tasked with generating prime numbers up to a certain limit. Each thread might have a portion of the range to check, and they might need to update a shared list or count of found primes. A simplified prime generation module could involve a function like:
if n < 2:
return False
for i in range(2, int(n**0.5) + 1):
if n % i == 0:
return False
return True
Now, let's imagine a concurrent prime generation task where threads need to add found primes to a shared list. A naive approach without synchronization might look like this:
def prime_generator_task(start, end):
for num in range(start, end):
if is_prime(num):
# Potential race condition here!
shared_primes_list.append(num)
The line shared_primes_list.append(num) is a critical section. If two threads find a prime number at nearly the same time and both attempt to append it to the list, the internal state of the list could become corrupted, or one append operation might be lost. This is a classic race condition.
To illustrate synchronization, we can use a mutex (mutual exclusion) lock. A mutex ensures that only one thread can access a shared resource (the critical section) at any given time. In Python, this can be achieved using the `threading.Lock` object.
Synchronized Approach:
- Define a Shared Object: The `shared_primes_list` is the shared object.
- Define a Lock: A lock object is created to protect the shared object.
- Identify Critical Sections: The code that accesses or modifies the shared object (e.g., `append` operation) is the critical section.
- Acquire and Release Lock: Before entering the critical section, a thread must acquire the lock. If the lock is already held by another thread, the current thread will block until the lock is released. After exiting the critical section, the thread must release the lock, allowing other waiting threads to acquire it.
Here's how the synchronized code would look:
shared_primes_list = []
primes_lock = threading.Lock() # Create a lock object
def is_prime(n):
if n < 2:
return False
for i in range(2, int(n**0.5) + 1):
if n % i == 0:
return False
return True
def synchronized_prime_generator_task(start, end):
for num in range(start, end):
if is_prime(num):
# Acquire the lock before accessing the shared list
primes_lock.acquire()
try: shared_primes_list.append(num) # Critical Section finally: # Always release the lock, even if an error occurs primes_lock.release()
In this synchronized version, when a thread finds a prime number, it first attempts to acquire `primes_lock`. If another thread is currently inside the critical section (appending to `shared_primes_list`), the current thread will wait. Once the lock is acquired, the thread appends the prime number and then releases the lock. This ensures that the `append` operation is atomic with respect to other threads trying to perform the same operation, preventing data corruption and ensuring that all found primes are correctly added to the list. Other synchronization primitives like semaphores, condition variables, and monitors can also be used depending on the specific coordination requirements.
What is parallelism? State the need for parallelism.
Answer
Sign in to view the complete answer paper.
Explain the Filter-Lock algorithm for implementing mutual exclusion among n-threads.
Answer
Sign in to view the complete answer paper.
Recall a simple lock-based concurrent FIFO queue. Write enq() and deq() methods and examine how these methods results in correctness property with a brief illustrations.
Answer
Sign in to view the complete answer paper.
What are sequential objects? Discuss briefly.
Answer
Sign in to view the complete answer paper.
Explain how sequential consistency is non-blocking with relevant example.
Answer
Sign in to view the complete answer paper.
Give a detail note on a dependent non-blocking progress condition.
Answer
Sign in to view the complete answer paper.
"Any nontrivial RMW register has consensus number at least 2". Prove the theorem.
Answer
Sign in to view the complete answer paper.
Explain the following operations with brief illustrations: i) compareAndSet() ii) getAndSet()
Answer
Sign in to view the complete answer paper.
Write down the lock-free universal algorithm and explain the execution of the lock-free universal construction with a brief illustration.
Answer
Sign in to view the complete answer paper.
State the merits and demerits of hand-over-hand locking mechanism.
Answer
Sign in to view the complete answer paper.
How to implement Optimistic synchronization mechanism on a linked list by concurrent threads? Write the complete pseudo code for add and remove methods of it and explain.
Answer
Sign in to view the complete answer paper.
What do you mean by lock-free stack? Explain how to implement lock-free stack operations with an example program code.
Answer
Sign in to view the complete answer paper.