SlideShare a Scribd company logo
Java Thread Synchronization
●

Creating a Java Thread

●

Synchronized Keyword

●

Wait and Notify
●

●

●

Java threads are a way to have different parts of your program
running at the same time.

For example, you can create an application that accepts input
from different users at the same time, each user handled by a
thread.
Also, most networking applications involve threads
–

you would need to create a thread that would wait for incoming
messages while the rest of your program handles your outgoing
messages.
●

There are two ways to create a java thread
–

Extending the Thread class

–

Implementing the runnable interface
●

We will create a thread that simply prints out a number 500
times in a row.
class MyThread extends Thread {
int i;
MyThread(int i) {
this.i = i;
}
public void run() {
for (int ctr=0; ctr < 500; ctr++) {
System.out.print(i);
}
}
}
●

To show the difference between parallel and non-parallel
execution, we have the following executable MyThreadDemo
class
class MyThreadDemo {
public static void main(String args[]) {
MyThread t1 = new MyThread(1);
MyThread t2 = new MyThread(2);
MyThread t3 = new MyThread(3);
t1.run();
t2.run();
t3.run();
System.out.print("Main ends");
}}
●

Upon executing MyThreadDemo, we get output that looks like
this
$ java MyThreadDemo
1111111111...22222222.....33333......Main ends

●

●

●

As can be seen, our program first executed t1's run method,
which prints 500 consecutive 1's.
After that t2's run method, which prints consecutuve 2's, and
so on.
Main ends appears at the last part of the output as it is the last
part of the program.
●

What happened was serial execution, no multithreaded
execution occurred
–

This is because we simply called MyThread's run() method
Java Thread Synchronization
●

To start parallel execution, we call MyThread's start() method,
which is built-in in all thread objects.
class MyThreadDemo {
public static void main(String args[]) {
MyThread t1 = new MyThread(1);
MyThread t2 = new MyThread(2);
MyThread t3 = new MyThread(3);
t1.start();
t2.start();
t3.start();
System.out.print("Main ends");
}}
●

When we run MyThreadDemo we can definitely see that three
run methods are executing at the same time
> java MyThreadDemo
111111111122331122321122333331111Main ends111333222...
Java Thread Synchronization
●

Note the appearance of the "Main ends" string in the middle of
the output sequence
> java MyThreadDemo
111111111122331122321122333331111Main ends111333222...

●

This indicates that the main method has already finished
executing while thread 1, thread 2 and thread 3 are still
running.
●

Running a main method creates a thread.
–

●

Normally, your program ends when the main thread ends.

However, creating and then running a thread's start method
creates a whole new thread that executes its run() method
independent of the main method.
●

●

Another way to create a thread is to implement the Runnable
interface.

This may be desired if you want your thread to extend another
class.
–

By extending another class, you will be unable to extend class thread
as Java classes can only extend a single class.

–

However, a class can implement more than one interface.
●

The following is our MyThread class created by implementing
the runnable interface.
class MyThread implements Runnable {
... <thread body is mostly the same>
}
●

Classes that implement Runnable are instantiated in a
different way.
–

Thread t1 = new Thread(new MyThread(1));
●

●

Note that implementing an interface requires you to define all
the methods in the interface

For the Runnable interface, you are required in your
implementing class to define the run() method or your
program will not run.
………………

……………………………
Pausing and Joining
Threads
Threads can be paused by the sleep() method.

●

For example, to have MyThread pause for half a second
before it prints the next number, we add the following lines of
code to our for loop.

●

for (int ctr=0; ctr < 500; ctr++) {
System.out.print(i);
try {
Thread.sleep(500); // 500 miliseconds
} catch (InterruptedException e) { }
}

●

Thread.sleep() is a static method of class thread and can
be invoked from any thread, including the main thread.
for (int ctr=0; ctr < 500; ctr++) {
System.out.print(i);
try {
Thread.sleep(500); // 500 miliseconds
} catch (InterruptedException e) { }
}

●

The InterruptedException is an unchecked exeception that is
thrown by code that stops a thread from running.
–

●

Unchecked exception causing lines must be enclosed in a try-catch, in
this case, Thread.sleep().

An InterruptedException is thrown when a thread is waiting,
sleeping, or otherwise paused for a long time and another
thread interrupts it using the interrupt() method in class
Thread.
●

●

You can also make a thread stop until another thread finishes
running by invoking a thread's join() method.

For instance, to make our main thread to stop running until
thread t1 is finished, we could simply say...
public static void main(String args[]) {
...
t1.start();
try {
t1.join();
} catch (InterruptedException e) { }
t2.start();
●

This would cause all the 1's to be printed out before thread
2 and thread 3 start.
………………

……………………………
Critical Section
Problem
●

●

This section we will find out how to implement a solution to the
critical section problem using Java

Recall that only a single process can enter its critical section,
all other processes would have to wait
–

No context switching occurs inside a critical section
●

Instead of printing a continuous stream of numbers, MyThread
calls a print10() method in a class MyPrinter
–

●

print10() prints 10 continuous numbers on a single line before a
newline.

Our goal is to have these 10 continuous numbers printed
without any context switches occuring.
–

Our output should be:
...
1111111111
1111111111
2222222222
3333333333
1111111111
...
●

We define a class MyPrinter that will have our print10()
method

class MyPrinter {
public void print10(int value) {
for (int i = 0; i < 10; i++) {
System.out.print(value);
}
System.out.println(""); // newline after 10 numbers
}
}
●

Instead of printing numbers directly, we use the print10()
method in MyThread, as shown by the following
class MyThread extends Thread {
int i;
MyPrinter p;
MyThread(int i) {
this.i = i;
p = new MyPrinter();
}
public void run() {
for (int ctr=0; ctr < 500; ctr++) {
p.print10(i);
}
}
}
●

First, we will try to see the output of just a single thread
running.
class MyThreadDemo {
public static void main(String args[]) {
MyThread t1 = new MyThread(1);
// MyThread t2 = new MyThread(2);
// MyThread t3 = new MyThread(3);
t1.start();
// t2.start();
// t3.start();
System.out.print("Main ends");
}}

We comment out
the other threads
for now...
●

When we run our MyThreadDemo, we can see that the output
really does match what we want.
> java MyThreadDemo
1111111111
1111111111
1111111111
1111111111
1111111111
...
●

However, let us try to see the output with other threads.

class MyThreadDemo {
public static void main(String args[]) {
MyThread t1 = new MyThread(1);
MyThread t2 = new MyThread(2);
MyThread t3 = new MyThread(3);
t1.start();
t2.start();
t3.start();
System.out.print("Main ends");
}}

We run all three
threads
Our output would look like the following

●

> java MyThreadDemo
1111111111
111112222222
1111
22233333332
...
●

We do not achieve our goal of printing 10 consecutive
numbers in a row
–

all three threads are executing the print10's method at the same
time, thus having more than one number appearing on a single
line.
●

To achieve our goal there should not be any context switches
happening inside print10()
–

●

●

Only a single thread should be allowed to execute inside print10()

As can be seen, this is an example of the critical section
problem
To solve this, we can use some of the techniques discussed in
our synchronization chapter
●
●
●
●

Busy Wait
Wait and Notify

Semaphores
Monitors
●

●

Now we will discuss Java's
solution to the critical
section problem
Java uses a monitor
construct
–

Only a single thread may run
inside the monitor

Even if P2 is calling method2(), it
has to wait for P1 to finish
●

To turn an object into a monitor, simply put the synchronized
keyword on your method definitions
–

Only a single thread can run any synchronized method in an object

class MyPrinter {
public synchronized void print10(int value) {
for (int i = 0; i < 10; i++) {
System.out.print(value);
}
System.out.println(""); // newline after 10
numbers
}
}
However, even if we did turn our print10() method into a
synchronized method, it will still not work

●

> java MyThreadDemo
1111111111
111112222222
1111
22233333332
...

●

To find out how to make it work, we need to first find out
how the synchronized keyword works
●

Every object in Java has an intrinsic lock
●

When a thread tries to run a synchronized method, it first tries
to get a lock on the object
●

If a thread is successful, then it owns the lock and executes
the synchronized code.
●

Other threads cannot run the synchronized code because the
lock is unavailable
●

Threads can only enter once the thread owning the lock
leaves the synchronized method
●

Waiting threads would then compete on who gets to go next
●

So why doesn't our example work?

●

Because each thread has its own copy of the MyPrinter object!

class MyThread extends Thread {
int i;
MyPrinter p;
MyThread(int i) {
this.i = i;
p = new MyPrinter();
// each MyThread creates
its own MyPrinter!
}
public void run() {
for (int ctr=0; ctr < 500; ctr++) {
p.print10(i);
}
}
}
Java Thread Synchronization
●

Recall our definition of synchronized methods
–

●

Only a single thread can run any synchronized method in an object

Since each thread has its own MyPrinter object, then no
locking occurs
●

So, to make it work, all threads must point to the same
MyPrinter object
●

Note how all MyThreads now have the same MyPrinter object

class MyThread extends Thread {
int i;
MyPrinter p;
MyThread(int i, MyPrinter p) {
this.i = i; this.p = p
}
public synchronized void run() {
for (int ctr=0; ctr < 500;
ctr++) {
p.print10(i);
}
}
}

class MyThreadDemo {
public static void main(String args[]) {
MyPrinter p = new
MyPrinter();
MyThread t1 = new
MyThread(1,p);
MyThread t2 = new
MyThread(2,p);
MyThread t3 = new
MyThread(3,p);
t1.start();
t2.start();
t3.start();
}}
Java Thread Synchronization
●

A way to visualize it is that all Java objects can be doors
–

A thread tries to see if the door is open

–

Once the thread goes through the door, it locks it behind it,

–

No other threads can enter the door because our first thread has
locked it from the inside

–

Other threads can enter if the thread inside unlocks the door and goes
out

–

Lining up will only occur if everyone only has a single door to the
critical region
●

Running MyThreadDemo now correctly shows synchronized
methods at work
>java MyThreadDemo
1111111111
1111111111
1111111111
2222222222
3333333333
...
●

Only a single thread can run any synchronized method in an
object
–

●

If an object has a synchronized method and a regular method, only one
thread can run the synchronized method while multiple threads can run
the regular method

Threads that you want to have synchronized must share the
same monitor object
●

●

Aside from synchronized methods, Java also allows for
synchronized blocks.

You must specify what object the intrinsic lock comes from
●

Our print10() implementation, done using synchronized
statements, would look like this

class MyPrinter {
public void print10(int value) {
synchronized(this) {
for (int i = 0; i < 10; i++) {
System.out.print(value);
}
System.out.println(""); // newline after
10 numbers
}
}
}
We use a MyPrinter object for the
lock, replicating what the
synchronized method does
●

●

Synchronized blocks allow for flexibility, in the case if we want
our intrinsic lock to come from an object other than the current
object.
For example, we could define MyThread's run method to
perform the lock on the MyPrinter object before calling print10

class MyThread extends Thread {
MyPrinter p;
...
public void run() {
for (int i = 0; i < 100; i++) {
synchronized(p) {
p.print10(value);
}
}}}

Note that any lines
before and after our
synchronized block can
be executed
concurrently by threads
●

Also, the use of the synchronized block allows for more
flexibility by allowing different parts of code to be locked with
different objects.
●

For example, consider a modified MyPrinter which has two
methods, which we'll allow to run concurrently

class MyPrinter {
The blocks inside print10() and
Object lock1 = new Object();
squareMe() can run at the same time
Object lock2 = new Object();
because they use different objects for
public void print10(int value) {
their locking mechanism
synchronized(lock1) {
for (int i = 0; i < 10; i++) {
System.out.print(value);
}
System.out.println(""); // newline after 10 numbers
}
}
Synchronization still applies. For
public int squareMe(int i) {
example only a single thread can
synchronized (lock2) {
run the synchronized block in
return i * i;
squareMe() at any point in time
}
}
}
Java Thread Synchronization
●

Creating a Java Thread

●

Synchronized Keyword

●

Wait and Notify

●

High Level Cuncurrency Objects
●

●

We will now discuss a solution to the Producer-Consumer
problem.

Instead of using beer, the producer will store in a shared stack
a random integer value which will be retrieved by the
consumer process.
Java Thread Synchronization
Java Thread Synchronization
●

As can be seen, we would need to have a place to store our
array of integers and our top variable, which should be shared
among our producer and consumer.
–

MAXCOUNT is the maximum number of items the Producer produces

–

We'll assume the maximum array size of 10000 for now

class SharedVars {
final int MAXCOUNT = 100;
int array[] = new int[10000];
int top;
// <more code to follow>
}
●

●

To keep things object-oriented, we will place the code for
placing values in the stack and getting values in the stack in
our SharedVars class
Our next slide shows our implementation
class SharedVars {
final int MAXCOUNT = 100;
int array[] = new int[10000];
int top;
// method for inserting a value
public void insertValue(int value) {
if (top < array.length) {
array[top] = value;
top++;
}
}
// method for getting a value
public int getValue() {
if (top > 0) {
top--;
return array[top];
}
else
return -1;

}}
Java Thread Synchronization
Java Thread Synchronization
Java Thread Synchronization
Java Thread Synchronization
Java Thread Synchronization
Java Thread Synchronization
Java Thread Synchronization
Java Thread Synchronization
Java Thread Synchronization
Java Thread Synchronization
Java Thread Synchronization
●

●

Now we will slowly build our Producer and Consumer class
We can say that our Producer and Consumer should be
implemented as threads.
–

Thus we have our code below, including a class that starts these
threads

class Producer extends Thread {
public void run() {
}
}

class Consumer extends Thread {
public void run() {
}
}

class PCDemo {
public static void main(String args[]) {
Producer p = new Producer();
Consumer c = new Consumer();
p.start();
c.start();
}}
●

Producer and Consumer should have the same SharedVars
object
class Producer extends Thread {
SharedVars sv;
Producer(SharedVars sv) {
this.sv = sv;
}
public void run() {
}
}

class Consumer extends Thread {
SharedVars sv;
Consumer(SharedVars sv) {
this.sv = sv;
}
public void run() {
}
}

class PCDemo {
public static void main(String args[]) {
SharedVars sv = new
SharedVars();
Producer p = new Producer(sv);
Consumer c = new Consumer(sv);
p.start();
c.start();
}}
●

There is no more need to modify our PCDemo class so we will
not show it anymore.
●

We want our producer to produce a random integer and store
it in SharedVars. Thus our Producer code would look like this
class Producer extends Thread {
SharedVars sv;
Producer(SharedVars sv) {
this.sv = sv;
}
public void run() {
int value = (int)(Math.random() * 100); // random value from
0 to 100
sv.insertValue(value);
System.out.println("Producer: Placing value: " + value);
}
}
●

We want our Producer to do this a hundred times, so we will
add a loop to our code
class Producer extends Thread {
SharedVars sv;
Producer(SharedVars sv) {
this.sv = sv;
}
public void run() {
for (int i = 0; i < 100; i++) {
int value = (int)(Math.random() * 100); // random
value from 0 to 100
sv.insertValue(value);
System.out.println("Producer: Placing value: " +
value);
}
}
}
●

Finally, we have our producer pause for a maximum of 5
seconds each time it places a value
class Producer extends Thread {
SharedVars sv;
Producer(SharedVars sv) {
this.sv = sv;
}
public void run() {
for (int i = 0; i < 100; i++) {
int value = (int)(Math.random() * 100); // random
value from 0 to 100
sv.insertValue(value);
System.out.println("Producer: Placing value: " +
value);
try {
Thread.sleep((int)(Math.random() *
5000)); // sleep 5s max

} catch (InterruptedException e) { }
}
}

}
●

Now, we want our consumer to get a value from SharedVars

class Consumer extends Thread {
SharedVars sv;
Consumer(SharedVars sv) {
this.sv = sv;
}
public void run() {
int value = sv.getValue();
System.out.println("Consumer: I got value:" + value);
}
}
●

We want to get a value 100 times

class Consumer extends Thread {
SharedVars sv;
Consumer(SharedVars sv) {
this.sv = sv;
}
public void run() {
for (int i = 0; i < 100; i++) {
int value = sv.getValue();
System.out.println("Consumer: I got value:" +
value);
}
}
}
●

Finally, just like producer, we pause for a maximum of 5
seconds on each loop
class Consumer extends Thread {
SharedVars sv;
Consumer(SharedVars sv) {
this.sv = sv;
}
public void run() {
for (int i = 0; i < 100; i++) {
int value = sv.getValue();
System.out.println("Consumer: I got value:" +
value);

try {
Thread.sleep((int)(Math.random() *
5000)); // sleep 5s max

} catch (InterruptedException e) { }
}
}
}
●

As was discussed in a previous chapter, we try to avoid a race
condition between insertValue() and getValue()

Consumer getValue(): top = top – 1
Producer insertValue(): array[top] = value // this would overwrite an existing value!
Producer insertValue(): top = top + 1
Consumer getValue(): return array[top] // consumer returns an already returned value
Java Thread Synchronization
●

●

We do not want getValue() and insertValue() to run at the
same time

Therefore, we modify SharedVars to use synchronized blocks
–

We could also use synchronized methods but we need some nonsynchronized commands
class SharedVars {
final int MAXCOUNT = 100;
int array[] = new int[10000];
int top;
public void insertValue(int value) { // method for inserting a value
synchronized(this) {
if (top < array.length) {
array[top] = value;
top++;
}
}
}
public int getValue() { // method for getting a value
synchronized(this) {
if (top > 0) {
top--;
return array[top];
}
else
return -1;
}
}
}
Java Thread Synchronization
Java Thread Synchronization
Upon executing our program, the output of our code would
look something like this:

●

Producer inserts value: 15
Consumer got: 15
Consumer got: -1
Producer inserts value: 50
Producer inserts value: 75
Consumer got: 75
...
●

Note that both Consumer and Producer are running at the
same time.
Producer inserts value: 15
Consumer got: 15
Consumer got: -1
Producer inserts value: 50
Producer inserts value: 75
Consumer got: 75
...
●

Notice that, if we try to get a value from the array and there
isn't any, we return a value -1.
–

–
●

You can see this clearly if you increase the Producer delay to 10s.

Producer adds a value every 10s, consumer gets one every 5s

Wouldn't it be better if we have our Consumer wait for the
Producer to produce something instead of just getting -1?
We could implement a busy wait for this

●

public int getValue() {
while (top <= 0) { } // do nothing
synchronized(this) {
top--;
return array[top];
}}
●

Note how we placed this outside our synchronized block
–

Having our busy wait inside would mean blocking out producer
thread from insertValue(), which is what is needed to break the
busy wait
●

●

●

A better solution is to use the wait() method, defined in class
Object, and is therefore inherited by all objects

A thread invoking wait() will suspend the thread
However, a thread invoking wait() must own the intrinsic lock
of the object it is calling wait() from
–

●

If we are going to call this.wait() it has to be in synchronized(this) block

Also, as with all methods that suspend thread execution, like
join() and sleep(), our wait() method must be in a try-catch
block that catches InterruptedExceptions.
// called by Consumer thread
public int getValue() {
synchronized(this) {
if (top <= 0) {
try {
this.wait();
} catch (InterruptedException e) { }
}
top--;
return array[top];

}}
●

●

All threads that call wait() on an object are placed in a pool of
waiting threads for that object.

Execution resumes when another thread calls the notify()
method of the object our first thread is waiting on
–

The notify() method is defined in class Object.

–

All objects have wait() and notify()
●

For our example, our producer thread, after inserting on an
empty array, would notify the consumer thread that it has
placed a value in our array by calling the notify() method on
the SharedVars object
–

Recall that Producer and Consumer both have a reference to the same
SharedVars object.

–

The producer calling notify() from insertValue() would inform any the
consumer waiting on the same SharedVar object.
// called by producer
public void insertValue(int value) {
synchronized(this) {
if (top < array.length) {
array[top] = value;
top++;
if (top == 1) { // we just inserted on an empty array
this.notify(); // notify sleeping thread
}
}
}
}
class SharedVars {
final int MAXCOUNT = 100;
int array[] = new int[10000];
int top;
public void insertValue(int value) {
synchronized(this) {
if (top < array.length) {
array[top] = value;
top++;
if (top == 1) { // we just inserted on an empty array
this.notify(); // notify any sleeping thread
}
}
}
}
public int getValue() {
synchronized(this) {
if (top <= 0) {
try {
this.wait();
} catch (InterruptedException e) { }
}
top--;
return array[top];
}
}
}
●

●

When the notify() method of an object is called, then a single
waiting thread on that object is signaled to get ready to
resume execution.
After our Producer thread exits insertValue and releases the
lock, our Consumer thread gets the lock once again and
resumes its execution.
Java Thread Synchronization
Java Thread Synchronization
Java Thread Synchronization
Java Thread Synchronization
Java Thread Synchronization
Java Thread Synchronization
Java Thread Synchronization
Java Thread Synchronization
Java Thread Synchronization
●

●

Another method called notifyAll() notifies all the waiting
threads.

These waiting threads would then compete to see which
single thread resumes execution, the rest of the threads would
once again wait.
●

●

If you run the demo program again, you can see that, even if
the producer is slow, the consumer waits until the producer
gives out a value before getting that value
Note that you must also consider inserting on a full array
–

Producer must wait until consumer has taken away some values
before inserting

–

We will leave the implementation of this as an exercise
●

Note that this same thing must occur on inserting on a full
array
–

Producer must wait until consumer has taken away some values
before inserting

–

We will leave the implementation of this as an exercise.
Java Thread Synchronization
●

●

Alice and Bob are at the office. There is a doorway that they have
to pass through every now and then. Since Bob has good manners,
if he gets to the door, he always makes sure that he always opens
the door and waits for Alice to go through before he does. Alice by
herself simply goes through the door.
Your task is to write an Alice and Bob thread that mimics this
behavior. To simulate having to pass through the door, have a delay
in each thread for a random amount of time, maximum of 5
seconds. The output of your code should look something like this:
Alice: I go through the door
Alice: I go through the door

Bob: I get to the door and wait for Alice...
Alice: I go through the door

Bob: I follow Alice
Alice: I go through the door
Bob: I get to the door and wait for Alice

More Related Content

PPT
Thread model in java
PPSX
Java Multi-threading programming
PPTX
Multi-threaded Programming in JAVA
PPT
Java Threads
PPT
Java And Multithreading
PDF
Java thread life cycle
PPTX
Multithreading in java
PPTX
Basics of Java Concurrency
Thread model in java
Java Multi-threading programming
Multi-threaded Programming in JAVA
Java Threads
Java And Multithreading
Java thread life cycle
Multithreading in java
Basics of Java Concurrency

What's hot (20)

PPTX
PDF
Java threads
PPTX
Interface in java
PPT
Synchronization.37
PPTX
oops concept in java | object oriented programming in java
PPT
Java interfaces
PPTX
Multithreading in java
PDF
Methods in Java
PPT
SQLITE Android
PPTX
Java swing
PPTX
Inner classes in java
PPTX
Java program structure
ODP
Multithreading In Java
PPT
Java Socket Programming
PDF
Java Programming
PPTX
Chapter 07 inheritance
PPTX
Inheritance in java
PPS
Jdbc architecture and driver types ppt
PPT
Java packages
Java threads
Interface in java
Synchronization.37
oops concept in java | object oriented programming in java
Java interfaces
Multithreading in java
Methods in Java
SQLITE Android
Java swing
Inner classes in java
Java program structure
Multithreading In Java
Java Socket Programming
Java Programming
Chapter 07 inheritance
Inheritance in java
Jdbc architecture and driver types ppt
Java packages
Ad

Viewers also liked (20)

PPT
Learning Java 3 – Threads and Synchronization
PPT
Java Performance, Threading and Concurrent Data Structures
PPTX
Concurrency Programming in Java - 06 - Thread Synchronization, Liveness, Guar...
PDF
Java Course 10: Threads and Concurrency
PPT
Applet Architecture - Introducing Java Applets
PPTX
Multithread Programing in Java
PPT
Java multi threading
PPT
Threads And Synchronization in C#
PPT
Java layoutmanager
PPT
Learning Java 4 – Swing, SQL, and Security API
PPTX
java Unit4 chapter1 applets
PPTX
Java 8 parallel stream
PPTX
Event Handling in Java
PPT
Java thread
PPTX
Thread priorities
PPTX
Java class 3
PPTX
Java class 6
PDF
Concurrency Utilities in Java 8
PDF
Java 8 Stream API. A different way to process collections.
PPTX
Learning Java 3 – Threads and Synchronization
Java Performance, Threading and Concurrent Data Structures
Concurrency Programming in Java - 06 - Thread Synchronization, Liveness, Guar...
Java Course 10: Threads and Concurrency
Applet Architecture - Introducing Java Applets
Multithread Programing in Java
Java multi threading
Threads And Synchronization in C#
Java layoutmanager
Learning Java 4 – Swing, SQL, and Security API
java Unit4 chapter1 applets
Java 8 parallel stream
Event Handling in Java
Java thread
Thread priorities
Java class 3
Java class 6
Concurrency Utilities in Java 8
Java 8 Stream API. A different way to process collections.
Ad

Similar to Java Thread Synchronization (20)

PPTX
Chap3 multi threaded programming
PPTX
Java programming PPT. .pptx
PPT
this power point presentation is about concurrency and multithreading
PDF
Threads
DOCX
Threadnotes
PPTX
Multithreading in java
PPTX
Multithreading in java
PPT
Multithreading
PPT
04 threads
PPTX
Threads in Java
PDF
Java Multithreading
PPTX
PDF
1. learning programming with JavaThreads.pdf
PPTX
07. Parbdhdjdjdjsjsjdjjdjdjjkdkkdkdkt.pptx
PPT
Md09 multithreading
PPTX
multithreading to be used in java with good programs.pptx
PPT
Java Multithreading and Concurrency
DOCX
Module - 5 merged.docx notes about engineering subjects java
PPTX
unit-3java.pptx
PPTX
Multithreaded programming
Chap3 multi threaded programming
Java programming PPT. .pptx
this power point presentation is about concurrency and multithreading
Threads
Threadnotes
Multithreading in java
Multithreading in java
Multithreading
04 threads
Threads in Java
Java Multithreading
1. learning programming with JavaThreads.pdf
07. Parbdhdjdjdjsjsjdjjdjdjjkdkkdkdkt.pptx
Md09 multithreading
multithreading to be used in java with good programs.pptx
Java Multithreading and Concurrency
Module - 5 merged.docx notes about engineering subjects java
unit-3java.pptx
Multithreaded programming

Recently uploaded (20)

PPTX
Institutional Correction lecture only . . .
PDF
Black Hat USA 2025 - Micro ICS Summit - ICS/OT Threat Landscape
PDF
FourierSeries-QuestionsWithAnswers(Part-A).pdf
PDF
Classroom Observation Tools for Teachers
PPTX
Introduction_to_Human_Anatomy_and_Physiology_for_B.Pharm.pptx
PPTX
PPT- ENG7_QUARTER1_LESSON1_WEEK1. IMAGERY -DESCRIPTIONS pptx.pptx
PDF
Computing-Curriculum for Schools in Ghana
PDF
TR - Agricultural Crops Production NC III.pdf
PPTX
Cell Structure & Organelles in detailed.
PDF
3rd Neelam Sanjeevareddy Memorial Lecture.pdf
PPTX
Renaissance Architecture: A Journey from Faith to Humanism
PDF
Pre independence Education in Inndia.pdf
PDF
O7-L3 Supply Chain Operations - ICLT Program
PDF
2.FourierTransform-ShortQuestionswithAnswers.pdf
PDF
O5-L3 Freight Transport Ops (International) V1.pdf
PPTX
GDM (1) (1).pptx small presentation for students
PDF
01-Introduction-to-Information-Management.pdf
PDF
Microbial disease of the cardiovascular and lymphatic systems
PDF
Module 4: Burden of Disease Tutorial Slides S2 2025
PDF
102 student loan defaulters named and shamed – Is someone you know on the list?
Institutional Correction lecture only . . .
Black Hat USA 2025 - Micro ICS Summit - ICS/OT Threat Landscape
FourierSeries-QuestionsWithAnswers(Part-A).pdf
Classroom Observation Tools for Teachers
Introduction_to_Human_Anatomy_and_Physiology_for_B.Pharm.pptx
PPT- ENG7_QUARTER1_LESSON1_WEEK1. IMAGERY -DESCRIPTIONS pptx.pptx
Computing-Curriculum for Schools in Ghana
TR - Agricultural Crops Production NC III.pdf
Cell Structure & Organelles in detailed.
3rd Neelam Sanjeevareddy Memorial Lecture.pdf
Renaissance Architecture: A Journey from Faith to Humanism
Pre independence Education in Inndia.pdf
O7-L3 Supply Chain Operations - ICLT Program
2.FourierTransform-ShortQuestionswithAnswers.pdf
O5-L3 Freight Transport Ops (International) V1.pdf
GDM (1) (1).pptx small presentation for students
01-Introduction-to-Information-Management.pdf
Microbial disease of the cardiovascular and lymphatic systems
Module 4: Burden of Disease Tutorial Slides S2 2025
102 student loan defaulters named and shamed – Is someone you know on the list?

Java Thread Synchronization

  • 2. ● Creating a Java Thread ● Synchronized Keyword ● Wait and Notify
  • 3. ● ● ● Java threads are a way to have different parts of your program running at the same time. For example, you can create an application that accepts input from different users at the same time, each user handled by a thread. Also, most networking applications involve threads – you would need to create a thread that would wait for incoming messages while the rest of your program handles your outgoing messages.
  • 4. ● There are two ways to create a java thread – Extending the Thread class – Implementing the runnable interface
  • 5. ● We will create a thread that simply prints out a number 500 times in a row. class MyThread extends Thread { int i; MyThread(int i) { this.i = i; } public void run() { for (int ctr=0; ctr < 500; ctr++) { System.out.print(i); } } }
  • 6. ● To show the difference between parallel and non-parallel execution, we have the following executable MyThreadDemo class class MyThreadDemo { public static void main(String args[]) { MyThread t1 = new MyThread(1); MyThread t2 = new MyThread(2); MyThread t3 = new MyThread(3); t1.run(); t2.run(); t3.run(); System.out.print("Main ends"); }}
  • 7. ● Upon executing MyThreadDemo, we get output that looks like this $ java MyThreadDemo 1111111111...22222222.....33333......Main ends ● ● ● As can be seen, our program first executed t1's run method, which prints 500 consecutive 1's. After that t2's run method, which prints consecutuve 2's, and so on. Main ends appears at the last part of the output as it is the last part of the program.
  • 8. ● What happened was serial execution, no multithreaded execution occurred – This is because we simply called MyThread's run() method
  • 10. ● To start parallel execution, we call MyThread's start() method, which is built-in in all thread objects. class MyThreadDemo { public static void main(String args[]) { MyThread t1 = new MyThread(1); MyThread t2 = new MyThread(2); MyThread t3 = new MyThread(3); t1.start(); t2.start(); t3.start(); System.out.print("Main ends"); }}
  • 11. ● When we run MyThreadDemo we can definitely see that three run methods are executing at the same time > java MyThreadDemo 111111111122331122321122333331111Main ends111333222...
  • 13. ● Note the appearance of the "Main ends" string in the middle of the output sequence > java MyThreadDemo 111111111122331122321122333331111Main ends111333222... ● This indicates that the main method has already finished executing while thread 1, thread 2 and thread 3 are still running.
  • 14. ● Running a main method creates a thread. – ● Normally, your program ends when the main thread ends. However, creating and then running a thread's start method creates a whole new thread that executes its run() method independent of the main method.
  • 15. ● ● Another way to create a thread is to implement the Runnable interface. This may be desired if you want your thread to extend another class. – By extending another class, you will be unable to extend class thread as Java classes can only extend a single class. – However, a class can implement more than one interface.
  • 16. ● The following is our MyThread class created by implementing the runnable interface. class MyThread implements Runnable { ... <thread body is mostly the same> } ● Classes that implement Runnable are instantiated in a different way. – Thread t1 = new Thread(new MyThread(1));
  • 17. ● ● Note that implementing an interface requires you to define all the methods in the interface For the Runnable interface, you are required in your implementing class to define the run() method or your program will not run.
  • 19. Threads can be paused by the sleep() method. ● For example, to have MyThread pause for half a second before it prints the next number, we add the following lines of code to our for loop. ● for (int ctr=0; ctr < 500; ctr++) { System.out.print(i); try { Thread.sleep(500); // 500 miliseconds } catch (InterruptedException e) { } } ● Thread.sleep() is a static method of class thread and can be invoked from any thread, including the main thread.
  • 20. for (int ctr=0; ctr < 500; ctr++) { System.out.print(i); try { Thread.sleep(500); // 500 miliseconds } catch (InterruptedException e) { } } ● The InterruptedException is an unchecked exeception that is thrown by code that stops a thread from running. – ● Unchecked exception causing lines must be enclosed in a try-catch, in this case, Thread.sleep(). An InterruptedException is thrown when a thread is waiting, sleeping, or otherwise paused for a long time and another thread interrupts it using the interrupt() method in class Thread.
  • 21. ● ● You can also make a thread stop until another thread finishes running by invoking a thread's join() method. For instance, to make our main thread to stop running until thread t1 is finished, we could simply say... public static void main(String args[]) { ... t1.start(); try { t1.join(); } catch (InterruptedException e) { } t2.start(); ● This would cause all the 1's to be printed out before thread 2 and thread 3 start.
  • 23. ● ● This section we will find out how to implement a solution to the critical section problem using Java Recall that only a single process can enter its critical section, all other processes would have to wait – No context switching occurs inside a critical section
  • 24. ● Instead of printing a continuous stream of numbers, MyThread calls a print10() method in a class MyPrinter – ● print10() prints 10 continuous numbers on a single line before a newline. Our goal is to have these 10 continuous numbers printed without any context switches occuring. – Our output should be: ... 1111111111 1111111111 2222222222 3333333333 1111111111 ...
  • 25. ● We define a class MyPrinter that will have our print10() method class MyPrinter { public void print10(int value) { for (int i = 0; i < 10; i++) { System.out.print(value); } System.out.println(""); // newline after 10 numbers } }
  • 26. ● Instead of printing numbers directly, we use the print10() method in MyThread, as shown by the following class MyThread extends Thread { int i; MyPrinter p; MyThread(int i) { this.i = i; p = new MyPrinter(); } public void run() { for (int ctr=0; ctr < 500; ctr++) { p.print10(i); } } }
  • 27. ● First, we will try to see the output of just a single thread running. class MyThreadDemo { public static void main(String args[]) { MyThread t1 = new MyThread(1); // MyThread t2 = new MyThread(2); // MyThread t3 = new MyThread(3); t1.start(); // t2.start(); // t3.start(); System.out.print("Main ends"); }} We comment out the other threads for now...
  • 28. ● When we run our MyThreadDemo, we can see that the output really does match what we want. > java MyThreadDemo 1111111111 1111111111 1111111111 1111111111 1111111111 ...
  • 29. ● However, let us try to see the output with other threads. class MyThreadDemo { public static void main(String args[]) { MyThread t1 = new MyThread(1); MyThread t2 = new MyThread(2); MyThread t3 = new MyThread(3); t1.start(); t2.start(); t3.start(); System.out.print("Main ends"); }} We run all three threads
  • 30. Our output would look like the following ● > java MyThreadDemo 1111111111 111112222222 1111 22233333332 ... ● We do not achieve our goal of printing 10 consecutive numbers in a row – all three threads are executing the print10's method at the same time, thus having more than one number appearing on a single line.
  • 31. ● To achieve our goal there should not be any context switches happening inside print10() – ● ● Only a single thread should be allowed to execute inside print10() As can be seen, this is an example of the critical section problem To solve this, we can use some of the techniques discussed in our synchronization chapter
  • 32. ● ● ● ● Busy Wait Wait and Notify Semaphores Monitors
  • 33. ● ● Now we will discuss Java's solution to the critical section problem Java uses a monitor construct – Only a single thread may run inside the monitor Even if P2 is calling method2(), it has to wait for P1 to finish
  • 34. ● To turn an object into a monitor, simply put the synchronized keyword on your method definitions – Only a single thread can run any synchronized method in an object class MyPrinter { public synchronized void print10(int value) { for (int i = 0; i < 10; i++) { System.out.print(value); } System.out.println(""); // newline after 10 numbers } }
  • 35. However, even if we did turn our print10() method into a synchronized method, it will still not work ● > java MyThreadDemo 1111111111 111112222222 1111 22233333332 ... ● To find out how to make it work, we need to first find out how the synchronized keyword works
  • 36. ● Every object in Java has an intrinsic lock
  • 37. ● When a thread tries to run a synchronized method, it first tries to get a lock on the object
  • 38. ● If a thread is successful, then it owns the lock and executes the synchronized code.
  • 39. ● Other threads cannot run the synchronized code because the lock is unavailable
  • 40. ● Threads can only enter once the thread owning the lock leaves the synchronized method
  • 41. ● Waiting threads would then compete on who gets to go next
  • 42. ● So why doesn't our example work? ● Because each thread has its own copy of the MyPrinter object! class MyThread extends Thread { int i; MyPrinter p; MyThread(int i) { this.i = i; p = new MyPrinter(); // each MyThread creates its own MyPrinter! } public void run() { for (int ctr=0; ctr < 500; ctr++) { p.print10(i); } } }
  • 44. ● Recall our definition of synchronized methods – ● Only a single thread can run any synchronized method in an object Since each thread has its own MyPrinter object, then no locking occurs
  • 45. ● So, to make it work, all threads must point to the same MyPrinter object
  • 46. ● Note how all MyThreads now have the same MyPrinter object class MyThread extends Thread { int i; MyPrinter p; MyThread(int i, MyPrinter p) { this.i = i; this.p = p } public synchronized void run() { for (int ctr=0; ctr < 500; ctr++) { p.print10(i); } } } class MyThreadDemo { public static void main(String args[]) { MyPrinter p = new MyPrinter(); MyThread t1 = new MyThread(1,p); MyThread t2 = new MyThread(2,p); MyThread t3 = new MyThread(3,p); t1.start(); t2.start(); t3.start(); }}
  • 48. ● A way to visualize it is that all Java objects can be doors – A thread tries to see if the door is open – Once the thread goes through the door, it locks it behind it, – No other threads can enter the door because our first thread has locked it from the inside – Other threads can enter if the thread inside unlocks the door and goes out – Lining up will only occur if everyone only has a single door to the critical region
  • 49. ● Running MyThreadDemo now correctly shows synchronized methods at work >java MyThreadDemo 1111111111 1111111111 1111111111 2222222222 3333333333 ...
  • 50. ● Only a single thread can run any synchronized method in an object – ● If an object has a synchronized method and a regular method, only one thread can run the synchronized method while multiple threads can run the regular method Threads that you want to have synchronized must share the same monitor object
  • 51. ● ● Aside from synchronized methods, Java also allows for synchronized blocks. You must specify what object the intrinsic lock comes from
  • 52. ● Our print10() implementation, done using synchronized statements, would look like this class MyPrinter { public void print10(int value) { synchronized(this) { for (int i = 0; i < 10; i++) { System.out.print(value); } System.out.println(""); // newline after 10 numbers } } } We use a MyPrinter object for the lock, replicating what the synchronized method does
  • 53. ● ● Synchronized blocks allow for flexibility, in the case if we want our intrinsic lock to come from an object other than the current object. For example, we could define MyThread's run method to perform the lock on the MyPrinter object before calling print10 class MyThread extends Thread { MyPrinter p; ... public void run() { for (int i = 0; i < 100; i++) { synchronized(p) { p.print10(value); } }}} Note that any lines before and after our synchronized block can be executed concurrently by threads
  • 54. ● Also, the use of the synchronized block allows for more flexibility by allowing different parts of code to be locked with different objects.
  • 55. ● For example, consider a modified MyPrinter which has two methods, which we'll allow to run concurrently class MyPrinter { The blocks inside print10() and Object lock1 = new Object(); squareMe() can run at the same time Object lock2 = new Object(); because they use different objects for public void print10(int value) { their locking mechanism synchronized(lock1) { for (int i = 0; i < 10; i++) { System.out.print(value); } System.out.println(""); // newline after 10 numbers } } Synchronization still applies. For public int squareMe(int i) { example only a single thread can synchronized (lock2) { run the synchronized block in return i * i; squareMe() at any point in time } } }
  • 57. ● Creating a Java Thread ● Synchronized Keyword ● Wait and Notify ● High Level Cuncurrency Objects
  • 58. ● ● We will now discuss a solution to the Producer-Consumer problem. Instead of using beer, the producer will store in a shared stack a random integer value which will be retrieved by the consumer process.
  • 61. ● As can be seen, we would need to have a place to store our array of integers and our top variable, which should be shared among our producer and consumer. – MAXCOUNT is the maximum number of items the Producer produces – We'll assume the maximum array size of 10000 for now class SharedVars { final int MAXCOUNT = 100; int array[] = new int[10000]; int top; // <more code to follow> }
  • 62. ● ● To keep things object-oriented, we will place the code for placing values in the stack and getting values in the stack in our SharedVars class Our next slide shows our implementation
  • 63. class SharedVars { final int MAXCOUNT = 100; int array[] = new int[10000]; int top; // method for inserting a value public void insertValue(int value) { if (top < array.length) { array[top] = value; top++; } } // method for getting a value public int getValue() { if (top > 0) { top--; return array[top]; } else return -1; }}
  • 75. ● ● Now we will slowly build our Producer and Consumer class We can say that our Producer and Consumer should be implemented as threads. – Thus we have our code below, including a class that starts these threads class Producer extends Thread { public void run() { } } class Consumer extends Thread { public void run() { } } class PCDemo { public static void main(String args[]) { Producer p = new Producer(); Consumer c = new Consumer(); p.start(); c.start(); }}
  • 76. ● Producer and Consumer should have the same SharedVars object class Producer extends Thread { SharedVars sv; Producer(SharedVars sv) { this.sv = sv; } public void run() { } } class Consumer extends Thread { SharedVars sv; Consumer(SharedVars sv) { this.sv = sv; } public void run() { } } class PCDemo { public static void main(String args[]) { SharedVars sv = new SharedVars(); Producer p = new Producer(sv); Consumer c = new Consumer(sv); p.start(); c.start(); }}
  • 77. ● There is no more need to modify our PCDemo class so we will not show it anymore.
  • 78. ● We want our producer to produce a random integer and store it in SharedVars. Thus our Producer code would look like this class Producer extends Thread { SharedVars sv; Producer(SharedVars sv) { this.sv = sv; } public void run() { int value = (int)(Math.random() * 100); // random value from 0 to 100 sv.insertValue(value); System.out.println("Producer: Placing value: " + value); } }
  • 79. ● We want our Producer to do this a hundred times, so we will add a loop to our code class Producer extends Thread { SharedVars sv; Producer(SharedVars sv) { this.sv = sv; } public void run() { for (int i = 0; i < 100; i++) { int value = (int)(Math.random() * 100); // random value from 0 to 100 sv.insertValue(value); System.out.println("Producer: Placing value: " + value); } } }
  • 80. ● Finally, we have our producer pause for a maximum of 5 seconds each time it places a value class Producer extends Thread { SharedVars sv; Producer(SharedVars sv) { this.sv = sv; } public void run() { for (int i = 0; i < 100; i++) { int value = (int)(Math.random() * 100); // random value from 0 to 100 sv.insertValue(value); System.out.println("Producer: Placing value: " + value); try { Thread.sleep((int)(Math.random() * 5000)); // sleep 5s max } catch (InterruptedException e) { } } } }
  • 81. ● Now, we want our consumer to get a value from SharedVars class Consumer extends Thread { SharedVars sv; Consumer(SharedVars sv) { this.sv = sv; } public void run() { int value = sv.getValue(); System.out.println("Consumer: I got value:" + value); } }
  • 82. ● We want to get a value 100 times class Consumer extends Thread { SharedVars sv; Consumer(SharedVars sv) { this.sv = sv; } public void run() { for (int i = 0; i < 100; i++) { int value = sv.getValue(); System.out.println("Consumer: I got value:" + value); } } }
  • 83. ● Finally, just like producer, we pause for a maximum of 5 seconds on each loop class Consumer extends Thread { SharedVars sv; Consumer(SharedVars sv) { this.sv = sv; } public void run() { for (int i = 0; i < 100; i++) { int value = sv.getValue(); System.out.println("Consumer: I got value:" + value); try { Thread.sleep((int)(Math.random() * 5000)); // sleep 5s max } catch (InterruptedException e) { } } } }
  • 84. ● As was discussed in a previous chapter, we try to avoid a race condition between insertValue() and getValue() Consumer getValue(): top = top – 1 Producer insertValue(): array[top] = value // this would overwrite an existing value! Producer insertValue(): top = top + 1 Consumer getValue(): return array[top] // consumer returns an already returned value
  • 86. ● ● We do not want getValue() and insertValue() to run at the same time Therefore, we modify SharedVars to use synchronized blocks – We could also use synchronized methods but we need some nonsynchronized commands
  • 87. class SharedVars { final int MAXCOUNT = 100; int array[] = new int[10000]; int top; public void insertValue(int value) { // method for inserting a value synchronized(this) { if (top < array.length) { array[top] = value; top++; } } } public int getValue() { // method for getting a value synchronized(this) { if (top > 0) { top--; return array[top]; } else return -1; } } }
  • 90. Upon executing our program, the output of our code would look something like this: ● Producer inserts value: 15 Consumer got: 15 Consumer got: -1 Producer inserts value: 50 Producer inserts value: 75 Consumer got: 75 ... ● Note that both Consumer and Producer are running at the same time.
  • 91. Producer inserts value: 15 Consumer got: 15 Consumer got: -1 Producer inserts value: 50 Producer inserts value: 75 Consumer got: 75 ... ● Notice that, if we try to get a value from the array and there isn't any, we return a value -1. – – ● You can see this clearly if you increase the Producer delay to 10s. Producer adds a value every 10s, consumer gets one every 5s Wouldn't it be better if we have our Consumer wait for the Producer to produce something instead of just getting -1?
  • 92. We could implement a busy wait for this ● public int getValue() { while (top <= 0) { } // do nothing synchronized(this) { top--; return array[top]; }} ● Note how we placed this outside our synchronized block – Having our busy wait inside would mean blocking out producer thread from insertValue(), which is what is needed to break the busy wait
  • 93. ● ● ● A better solution is to use the wait() method, defined in class Object, and is therefore inherited by all objects A thread invoking wait() will suspend the thread However, a thread invoking wait() must own the intrinsic lock of the object it is calling wait() from – ● If we are going to call this.wait() it has to be in synchronized(this) block Also, as with all methods that suspend thread execution, like join() and sleep(), our wait() method must be in a try-catch block that catches InterruptedExceptions.
  • 94. // called by Consumer thread public int getValue() { synchronized(this) { if (top <= 0) { try { this.wait(); } catch (InterruptedException e) { } } top--; return array[top]; }}
  • 95. ● ● All threads that call wait() on an object are placed in a pool of waiting threads for that object. Execution resumes when another thread calls the notify() method of the object our first thread is waiting on – The notify() method is defined in class Object. – All objects have wait() and notify()
  • 96. ● For our example, our producer thread, after inserting on an empty array, would notify the consumer thread that it has placed a value in our array by calling the notify() method on the SharedVars object – Recall that Producer and Consumer both have a reference to the same SharedVars object. – The producer calling notify() from insertValue() would inform any the consumer waiting on the same SharedVar object.
  • 97. // called by producer public void insertValue(int value) { synchronized(this) { if (top < array.length) { array[top] = value; top++; if (top == 1) { // we just inserted on an empty array this.notify(); // notify sleeping thread } } } }
  • 98. class SharedVars { final int MAXCOUNT = 100; int array[] = new int[10000]; int top; public void insertValue(int value) { synchronized(this) { if (top < array.length) { array[top] = value; top++; if (top == 1) { // we just inserted on an empty array this.notify(); // notify any sleeping thread } } } } public int getValue() { synchronized(this) { if (top <= 0) { try { this.wait(); } catch (InterruptedException e) { } } top--; return array[top]; } } }
  • 99. ● ● When the notify() method of an object is called, then a single waiting thread on that object is signaled to get ready to resume execution. After our Producer thread exits insertValue and releases the lock, our Consumer thread gets the lock once again and resumes its execution.
  • 109. ● ● Another method called notifyAll() notifies all the waiting threads. These waiting threads would then compete to see which single thread resumes execution, the rest of the threads would once again wait.
  • 110. ● ● If you run the demo program again, you can see that, even if the producer is slow, the consumer waits until the producer gives out a value before getting that value Note that you must also consider inserting on a full array – Producer must wait until consumer has taken away some values before inserting – We will leave the implementation of this as an exercise
  • 111. ● Note that this same thing must occur on inserting on a full array – Producer must wait until consumer has taken away some values before inserting – We will leave the implementation of this as an exercise.
  • 113. ● ● Alice and Bob are at the office. There is a doorway that they have to pass through every now and then. Since Bob has good manners, if he gets to the door, he always makes sure that he always opens the door and waits for Alice to go through before he does. Alice by herself simply goes through the door. Your task is to write an Alice and Bob thread that mimics this behavior. To simulate having to pass through the door, have a delay in each thread for a random amount of time, maximum of 5 seconds. The output of your code should look something like this: Alice: I go through the door Alice: I go through the door Bob: I get to the door and wait for Alice... Alice: I go through the door Bob: I follow Alice Alice: I go through the door Bob: I get to the door and wait for Alice