Concurrency Flashcards

1
Q

What is a race condition?

A

Race condition is the only concurrent problem that can happen when two threads manipulate the same state (value) in the same time-lapse, the last thread to write the state will overwrite the state modification of the first thread.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
2
Q

What is mutual exclusion?

A

Mutual Exclusion also known as Mutex was first identified by Dijkstra. When a process is accessing shared variable is known as in critical section. When no two processes can be in Critical Section at the same time , this state is known as Mutual Exclusion.

It is property of concurrency control which is used to prevent race conditions.

Mutual Exclusion Devices: Locks, Reader’s Writer’s Problem,recursive locks,semaphores,monitor, message passing etc.

Requirements:

  • No more than one thread can be in its critical section at any one time.
  • A thread which dies in its critical non-critical section will not affect the others’ ability to continue.
  • No deadlock: if a thread wants to enter its critical section then it will eventually be allowed to do so.
  • No starvation.
  • Threads are not forced into lock-step execution of their critical sections.
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
3
Q

What is starvation and when does it occur?

A

Starvation occurs if two threads are running and one thread creates a lock which prevents a second thread from using a method. Normally the first thread should remove the lock quickly and the second thread can use the resource. If the first thread does not remove the lock, the second thread cannot continue.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
4
Q

What is a deadlock?

A

Deadlocks are the worst kind of starvation. They occur when two threads are both holding locks which the other needs to complete their task. Neither will give up its lock, which prevents the other from finishing, therefore neither can finish! There is no simple way to prevent deadlocks. They can be detected at runtime, but you need to think carefully about how threads will interact with locked objects.

Deadlock describes a situation where two or more threads are blocked forever, waiting for each other. Here’s an example.

Alphonse and Gaston are friends, and great believers in courtesy. A strict rule of courtesy is that when you bow to a friend, you must remain bowed until your friend has a chance to return the bow. Unfortunately, this rule does not account for the possibility that two friends might bow to each other at the same time.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
5
Q

What is a synchronised method?

A

The Java programming language provides two basic synchronization idioms: synchronized methods and synchronized statements.

To make a method synchronized, simply add the synchronized keyword to its declaration:

public class SynchronizedCounter {
    private int c = 0;
public synchronized void increment() {
    c++;
}

public synchronized void decrement() {
    c--;
}

public synchronized int value() {
    return c;
} }

If count is an instance of SynchronizedCounter, then making these methods synchronized has two effects:

  • First, it is not possible for two invocations of synchronized methods on the same object to interleave. When one thread is executing a synchronized method for an object, all other threads that invoke synchronized methods for the same object block (suspend execution) until the first thread is done with the object.
  • Second, when a synchronized method exits, it automatically establishes a happens-before relationship with any subsequent invocation of a synchronized method for the same object. This guarantees that changes to the state of the object are visible to all threads.

Synchronized methods enable a simple strategy for preventing thread interference and memory consistency errors: if an object is visible to more than one thread, all reads or writes to that object’s variables are done through synchronized methods. (An important exception: final fields, which cannot be modified after the object is constructed, can be safely read through non-synchronized methods, once the object is constructed) This strategy is effective, but can present problems with liveness.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
6
Q

When does a memory consistency error occur?

A

Memory consistency errors occur when different threads have inconsistent views of what should be the same data.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
7
Q

How do you avoid a memory consistency error?

A

The key to avoiding memory consistency errors is understanding the happens-before relationship. This relationship is simply a guarantee that memory writes by one specific statement are visible to another specific statement.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
8
Q

What actions create a happens-before relationship?

A

There are several actions that create happens-before relationships. One of them is synchronization.

Two actions that create happens-before relationships:

  • When a statement invokes Thread.start, every statement that has a happens-before relationship with that statement also has a happens-before relationship with every statement executed by the new thread. The effects of the code that led up to the creation of the new thread are visible to the new thread.
  • When a thread terminates and causes a Thread.join in another thread to return, then all the statements executed by the terminated thread have a happens-before relationship with all the statements following the successful join. The effects of the code in the thread are now visible to the thread that performed the join.
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
9
Q

What is thread interference and when does it happen?

A

Interference happens when two operations, running in different threads, but acting on the same data, interleave. This means that the two operations consist of multiple steps, and the sequences of steps overlap.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
10
Q

What are examples of thread contention?

A
  • Starvation -
    • Starvation describes a situation where a thread is unable to gain regular access to shared resources and is unable to make progress. This happens when shared resources are made unavailable for long periods by “greedy” threads.
  • Livelock -
    • A thread often acts in response to the action of another thread. If the other thread’s action is also a response to the action of another thread, then livelock may result. As with deadlock, livelocked threads are unable to make further progress. However, the threads are not blocked — they are simply too busy responding to each other to resume work. This is comparable to two people attempting to pass each other in a corridor: Alphonse moves to his left to let Gaston pass, while Gaston moves to his right to let Alphonse pass. Seeing that they are still blocking each other, Alphone moves to his right, while Gaston moves to his left. They’re still blocking each other, so…
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
11
Q

What problems do thread present?

A

Threads communicate primarily by sharing access to fields and the objects reference fields refer to. This form of communication is extremely efficient, but makes two kinds of errors possible:

  • thread interference
  • memory consistency errors.

The tool needed to prevent these errors is synchronization.

However, synchronization can introduce thread contention, which occurs when two or more threads try to access the same resource simultaneously and cause the Java runtime to execute one or more threads more slowly, or even suspend their execution.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
12
Q

What is concurrency?

A

Concurrency means that an application is making progress on more than one task at the same time (concurrently). Well, if the computer only has one CPU the application may not make progress on more than one task at exactly the same time, but more than one task is being processed at a time inside the application. It does not completely finish one task before it begins the next. Instead, the CPU switches between the different tasks until the tasks are complete.

It is possible to have a concurrent application even though it only has a single thread running inside it.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
13
Q

What is parallelism?

A

Parallelism means that an application splits its tasks up into smaller subtasks which can be processed in parallel, for instance on multiple CPUs at the exact same time.

To achieve true parallelism your application must have more than one thread running, or at least be able to schedule tasks for execution in other threads, processes, CPUs, graphics cards etc.

As you can see, concurrency is related to how an application handles multiple tasks it works on. An application may process one task at at time (sequentially) or work on multiple tasks at the same time (concurrently).

Parallelism on the other hand, is related to how an application handles each individual task. An application may process the task serially from start to end, or split the task up into subtasks which can be completed in parallel.

As you can see, an application can be concurrent, but not parallel. This means that it processes more than one task at the same time, but the thread is only executing on one task at a time. There is no parallel execution of tasks going in parallel threads / CPUs.

An application can also be parallel but not concurrent. This means that the application only works on one task at a time, and this task is broken down into subtasks which can be processed in parallel. However, each task (+ subtask) is completed before the next task is split up and executed in parallel.

Additionally, an application can be neither concurrent nor parallel. This means that it works on only one task at a time, and the task is never broken down into subtasks for parallel execution.

Finally, an application can also be both concurrent and parallel, in that it both works on multiple tasks at the same time, and also breaks each task down into subtasks for parallel execution. However, some of the benefits of concurrency and parallelism may be lost in this scenario, as the CPUs in the computer are already kept reasonably busy with either concurrency or parallelism alone. Combining it may lead to only a small performance gain or even performance loss. Make sure you analyze and measure before you adopt a concurrent parallel model blindly.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
14
Q

How do you create and start a new thread?

A
Creating a thread in Java is done like this:
  Thread thread = new Thread();

To start the Java thread you will call its start() method, like this:
thread.start();

This example doesn’t specify any code for the thread to execute. Therfore the thread will stop again right away after it is started.

There are two ways to specify what code the thread should execute. The first is to create a subclass of Thread and override the run() method. The second method is to pass an object that implements Runnable (java.lang.Runnable) to the Thread constructor.

The first way to specify what code a thread is to run, is to create a subclass of Thread and override the run() method. The run() method is what is executed by the thread after you call start(). Here is an example of creating a Java Thread subclass:

public class MyThread extends Thread {

public void run(){
   System.out.println("MyThread running");
}   }

To create and start the above thread you can do like this:

 MyThread myThread = new MyThread();
  myTread.start();

You can also create an anonymous subclass of Thread like this:

Thread thread = new Thread(){
    public void run(){
      System.out.println("Thread Running");
    }
  }

thread.start();

The second way to specify what code a thread should run is by creating a class that implements the java.lang.Runnable interface. A Java object that implements the Runnable interface can be executed by a Java Thread.

The Runnable interface is a standard Java Interface that comes with the Java platform. The Runnable interface only has a single method run().

There are three ways to implement the Runnable interface:

  1. Create a Java class that implements the Runnable interface.
  2. Create an anonymous class that implements the Runnable interface.
  3. Create a Java Lambda that implements the Runnable interface.
Java Class Implements Runnable:
public class MyRunnable implements Runnable {
public void run(){
   System.out.println("MyRunnable running");
}   }

All this Runnable implementation does is to print out the text MyRunnable running. After printing that text, the run() method exits, and the thread running the run() method will stop.

Anonymous Implementation of Runnable:
Runnable myRunnable =
    new Runnable(){
        public void run(){
            System.out.println("Runnable running");
        }
    }

Apart from being an anononymous class, this example is quite similar to the example that used a custom class to implement the Runnable interface.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
15
Q

What is a thread in java?

A

A Java Thread is like a virtual CPU that can execute your Java code - inside your Java application. when a Java application is started its main() method is executed by the main thread - a special thread that is created by the Java VM to run your application. From inside your application you can create and start more threads which can execute parts of your application code in parallel with the main thread.

Java threads are objects like any other Java objects. Threads are instances of class java.lang.Thread, or instances of subclasses of this class. In addition to being objects, java threads can also execute code.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
16
Q

How do you start a thread with runnable?

A
To have the run() method executed by a thread, pass an instance of a class, anonymous class or lambda expression that implements the Runnable interface to a Thread in its constructor. Here is how that is done:
Runnable runnable = new MyRunnable(); // or an anonymous class, or lambda...
Thread thread = new Thread(runnable);
thread.start();

When the thread is started it will call the run() method of the MyRunnable instance instead of executing it’s own run() method. The above example would print out the text “MyRunnable running”.

Common Pitfall: Calling run() Instead of start():
When creating and starting a thread a common mistake is to call the run() method of the Thread instead of start(), like this:
Thread newThread = new Thread(MyRunnable());
newThread.run(); //should be start();

At first you may not notice anything because the Runnable’s run() method is executed like you expected. However, it is NOT executed by the new thread you just created. Instead the run() method is executed by the thread that created the thread. In other words, the thread that executed the above two lines of code. To have the run() method of the MyRunnable instance called by the new created thread, newThread, you MUST call the newThread.start() method.

17
Q

How do you find out what the “current thread” is?

A

The Thread.currentThread() method returns a reference to the Thread instance executing currentThread() . This way you can get access to the Java Thread object representing the thread executing a given block of code. Here is an example of how to use Thread.currentThread() :

Thread thread = Thread.currentThread();

Once you have a reference to the Thread object, you can call methods on it. For instance, you can get the name of the thread currently executing the code like this:

String threadName = Thread.currentThread().getName();

18
Q

Why is runnable preferred to thread?

A
  1. Implementing Runnable is the preferred way to do it. Here, you’re not really specializing or modifying the thread’s behavior. You’re just giving the thread something to run. That means composition is the better way to go.
  2. Java only supports single inheritance, so you can only extend one class.
  3. Instantiating an interface gives a cleaner separation between your code and the implementation of threads.
  4. Implementing Runnable makes your class more flexible. If you extend Thread then the action you’re doing is always going to be in a thread. However, if you implement Runnable it doesn’t have to be. You can run it in a thread, or pass it to some kind of executor service, or just pass it around as a task within a single threaded application.
  5. If you are working on JDK 4 or lesser, then there is bug :
    http://bugs.java.com/bugdatabase/view_bug.do;jsessionid=5869e03fee226ffffffffc40d4fa881a86e3:WuuT?bug_id=4533087
    It’s fixed in Java 1.5 but Sun doesn’t intend to fix it in 1.4.
    The issue is that at construction time, a Thread is added to a list of references in an internal thread table. It won’t get removed from that list until its start() method has completed. As long as that reference is there, it won’t get garbage collected.

In general, I would recommend using something like Runnable rather than Thread because it allows you to keep your work only loosely coupled with your choice of concurrency. For example, if you use a Runnable and decide later on that this doesn’t in fact require it’s own Thread, you can just call threadA.run().

19
Q

What threads are involved in the lifecycle of a SwingWorker?

A

There are three threads involved in the life cycle of a SwingWorker:

  • Current thread: The execute() method is called on this thread. It schedules SwingWorker for the execution on a worker thread and returns immediately. One can wait for the SwingWorker to complete using the get methods.
  • Worker thread: The doInBackground() method is called on this thread. This is where all background activities should happen. To notify PropertyChangeListeners about bound properties changes use the firePropertyChange and getPropertyChangeSupport() methods. By default, there are two bound properties available: state and progress.
  • Event Dispatch Thread: All Swing related activities occur on this thread. SwingWorker invokes the process() and done() methods and notifies any PropertyChangeListeners on this thread.