Academic Integrity: tutoring, explanations, and feedback — we don’t complete graded work or submit on a student’s behalf.

In this lab, we examine how multithreading can lead to the synchronization probl

ID: 3815729 • Letter: I

Question

In this lab, we examine how multithreading can lead to the synchronization problem known as race condition. We also examine how this problem can be solved using 2 constructs provided by the operating system: semaphores and monitors.

1. Race condition

A race condition occurs when two or more threads can access shared data and they try to change it concurrently. Because the kernel can swap between threads at any time, you don't know the order in which the threads will attempt to access the shared data.

In the following, we will create a class that stores a variable, global, initialized to 0.We also create two Thread classes that attempt to access the shared variable. IncrementingThread is a thread that increments global 90,000,000 times, while DecrementingThread concurrently decrements global the same number of times.

1. What is the expected value of global when both threads have finished executing?

A race condition occurs when two or more threads can access shared data and they try to change it concurrently. Because the kernel can swap between threads at any time, you don't know the order in which the threads will attempt to access the shared data.

In the following, we will create a class that stores a variable, global, initialized to 0.We also create two Thread classes that attempt to access the shared variable. IncrementingThread is a thread that increments global 90,000,000 times, while DecrementingThread concurrently decrements global the same number of times.

Open a terminal

Move to the labs directory that you created in lab 1:

student@Ubuntu:~$ cd ~/labs

Create a new directory called lab3:

student@Ubuntu:~/labs$ mkdir lab3

Move to lab3:

student@Ubuntu:~/labs$ cd lab3

Open an editor (vi or gedit) and create all 4 classes GlobalClass.java, IncrementingThread.java, DecrementingThread.java and RaceConditionDemo.java that are listed below. Save the classes into the lab3 directory.

Compile the classes:

student@Ubuntu:~/labs/lab3$ javac *.java

Run the RaceConditionDemo class several times:

student@Ubuntu:~ /labs/lab3 $ java RaceConditionDemo

What is the output of this program, most of the times? Is it what you expected?

public class GlobalClass {

private int global = 0;

public void incrementGlobal(){

global++;

}

public void decrementGlobal(){

global--;

}

public int getGlobal() {

return global;

}

}

public class IncrementingThread extends Thread {

private GlobalClass globalClass;

public IncrementingThread(GlobalClass globalClass) {

this.globalClass = globalClass;

}

public void run(){

for(int i = 0; i < 90000000; i++){

globalClass.incrementGlobal();

}

}

}

public class DecrementingThread extends Thread {

private GlobalClass globalClass;

public DecrementingThread(GlobalClass globalClass) {

this.globalClass = globalClass;

}

public void run(){

for(int i = 0; i < 90000000; i++){

globalClass.decrementGlobal();

}

}

}

public class RaceConditionDemo {

public static void main(String[] args) {

GlobalClass globalClass = new GlobalClass();

IncrementingThread it = new IncrementingThread(globalClass);

it.start();

DecrementingThread dt = new DecrementingThread(globalClass);

dt.start();

try {

it.join();

dt.join();

} catch( InterruptedException e){

System.out.println(e.getMessage());

}

System.out.println("Final global = " + globalClass.getGlobal());

}

}

public class GlobalClass {

private int global = 0;

public void incrementGlobal(){

global++;

}

public void decrementGlobal(){

global--;

}

public int getGlobal() {

return global;

}

}

Explanation / Answer

If we expect that we are having 2 threads here, so both should be given the processor to execute themselves for equal amount of time, the output value of 'global' variable should be 0.

But, this is the ideal thing, this never happens in actual CPU processing. You are running 2 threads, IncrementingThread and DecrementingThread.

And both of them are operating on the same data, int variable 'global'.

So, the final value depends on which thread got chance to execute for how much time.

Every time here you will get the different output.

For example, I executed this code in my terminal, and the outputs I got was every time the different numbers :

-85216120

-66827414

-75262593

73895139

-62992199

86205749

-56188793

83092

-83065380

-796727

-45941748

-75928168

These outputs will have the range [-90000000, 90000000].

If only the DecrementingThread gets chance to execute, -90000000 is printed.If only the IncrementingThread is getting chance to execute, 90000000 is printed. But this is not happening in real.

Both the threads will get the chance to execute, and the result will depend on which thread executed for how much time. If the IncrementingThread is executed for more time than the DecrementingThread, the result will be positive number. Otherwise the result will be the negative number if DecrementingThread gets more time to execute.

This is the examination you are supposed to carry out here.

This is the perfect example of Race Condition. And as mentioned in the first line, using monitor or semaphore can solve this issue of race condition.

Hire Me For All Your Tutoring Needs
Integrity-first tutoring: clear explanations, guidance, and feedback.
Drop an Email at
drjack9650@gmail.com
Chat Now And Get Quote