Java Interview Questions: MultiThreading and Synchronization
Java Interview Questions: MultiThreading and Synchronization
MultiThreading
What
is
the
need
for
Threads
in
Java?
Threads
allow
Java
code
to
run
in
parallel.
Lets
look
at
an
example
to
understand
what
we
can
do
with
Threads.
Need
for
Threads
We
are
creating
a
Cricket
Statistics
Application.
Let's
say
the
steps
involved
in
the
application
are
Steps
I,
II
and
III
are
independent
and
can
be
run
in
parallel
to
each
other.
Run
individually
this
program
takes
160
minutes.
We
would
want
to
run
this
program
in
lesser
time.
Threads
can
be
a
solution
to
this
problem.
Threads
allow
us
to
run
STEP
I,
II
and
III
in
parallel
and
run
Step
IV
when
all
Steps
I,
II
and
III
are
completed.
Below
example
shows
the
way
we
would
write
code
usually
without
using
Threads.
ThreadExamples
example
=
new
ThreadExamples();
example.downloadAndStoreBattingStatistics();
example.downloadAndStoreBowlingStatistics();
example.downloadAndStoreFieldingStatistics();
example.mergeAndAnalyze();
NEW;
RUNNABLE;
RUNNING;
BLOCKED/WAITING;
TERMINATED/DEAD;
Description
A
thread
is
in
NEW
state
when
an
object
of
the
thread
is
created
but
the
start
method
is
not
yet
called.
At
the
end
of
line
1,
battingThread1
is
in
NEW
state.
A
thread
is
in
RUNNABLE
state
when
it
is
eligible
to
run,
but
not
running
yet.
(A
number
of
Threads
can
be
in
RUNNABLE
state.
Scheduler
selects
which
Thread
to
move
to
RUNNING
state).
In
the
above
example,
sometimes
the
Batting
Statistics
thread
is
running
and
at
other
time,
the
Bowling
Statistics
Thread
is
running.
When
Batting
Statistics
thread
is
Running,
the
Bowling
Statistics
thread
is
ready
to
run.
Its
just
that
the
scheduler
picked
Batting
Statistics
thread
to
run
at
that
instance
and
vice-versa.
When
Batting
Statistics
thread
is
Running,
the
Bowling
Statistics
Thread
is
in
Runnable
state
(Note
that
the
Bowling
Statistics
Thread
is
not
waiting
for
anything
except
for
the
Scheduler
to
pick
it
up
and
run
it).
A
thread
is
RUNNING
state
when
its
the
one
that
is
currently
,
what
else
to
say,
Running.
A
thread
is
in
BLOCKED/WAITING/SLEEPING
state
when
it
is
not
eligible
to
be
run
by
the
Scheduler.
Thread
is
alive
but
is
waiting
for
something.
An
example
can
be
a
Synchronized
block.
If
Thread1
enters
synchronized
block,
it
blocks
all
the
other
threads
from
entering
synchronized
code
on
the
same
instance
or
class.
All
other
threads
are
said
to
be
in
Blocked
state.
A
thread
is
in
DEAD/TERMINATED
state
when
it
has
completed
its
execution.
Once
a
thread
enters
dead
state,
it
cannot
be
made
active
again.
Synchronization
What
is
synchronization
of
threads?
Since
Threads
run
in
parallel,
a
new
problem
arises.
What
if
thread1
modifies
data
which
is
being
accessed
by
thread2?
How
do
we
ensure
that
different
threads
dont
leave
the
system
in
an
inconsistent
state?
This
problem
is
usually
called
synchronization
problem.
Lets
first
look
at
an
example
where
this
problem
can
occur.
Consider
the
code
in
the
setAndGetSum
method.
int
setandGetSum(int
a1,
int
a2,
int
a3)
{
cell1
=
a1;
sleepForSomeTime();
cell2
=
a2;
sleepForSomeTime();
cell3
=
a3;
sleepForSomeTime();
return
cell1
+
cell2
+
cell3;
}
If
following
method
is
running
in
two
different
threads,
funny
things
can
happen.
After
setting
the
value
to
each
cell,
there
is
a
call
for
the
Thread
to
sleep
for
some
time.
After
Thread
1
sets
the
value
of
cell1,
it
goes
to
Sleep.
So,
Thread2
starts
executing.
If
Thread
2
is
executing
return
cell1
+
cell2
+
cell3;,
it
uses
cell1
value
set
by
Thread
1
and
cell2
and
cell3
values
set
by
Thread
2.
This
results
in
the
unexpected
results
that
we
see
when
the
method
is
run
in
parallel.
What
is
explained
is
one
possible
scenario.
There
are
several
such
scenarios
possible.
The
way
you
can
prevent
multiple
threads
from
executing
the
same
method
is
by
using
the
synchronized
keyword
on
the
method.
If
a
method
is
marked
synchronized,
a
different
thread
gets
access
to
the
method
only
when
there
is
no
other
thread
currently
executing
the
method.
Lets
mark
the
method
as
synchronized:
synchronized
int
setandGetSum(int
a1,
int
a2,
int
a3)
{
cell1
=
a1;
sleepForSomeTime();
cell2
=
a2;
sleepForSomeTime();
cell3
=
a3;
sleepForSomeTime();
return
cell1
+
cell2
+
cell3;
}
Static
methods
and
block
are
synchronized
on
the
class.
Instance
methods
and
blocks
are
synchronized
on
the
instance
of
the
class
i.e.
an
object
of
the
class.
Static
synchronized
methods
and
instance
synchronized
methods
dont
affect
each
other.
This
is
because
they
are
synchronized
on
two
different
things.
static
int
getCount2(){
synchronized
(SynchronizedSyntaxExample.class)
{
return
count;
}
}
Lets
say
we
would
want
to
run
thread2
and
thread3
in
parallel
but
thread4
can
only
run
when
thread3
is
finished.
This
can
be
achieved
using
join
method.
Join
method
example
Look
at
the
example
code
below:
thread3.start();
thread2.start();
thread3.join();//wait
for
thread
3
to
complete
System.out.println("Thread3
is
completed.");
thread4.start();
thread3.join()
method
call
force
the
execution
of
main
method
to
stop
until
thread3
completes
execution.
After
that,
thread4.start()
method
is
invoked,
putting
thread4
into
a
Runnable
State.
Overloaded
Join
method
Join
method
also
has
an
overloaded
method
accepting
time
in
milliseconds
as
a
parameter.
thread4.join(2000);
What
is
a
deadlock?
Lets
consider
a
situation
where
thread1
is
waiting
for
thread2
(
thread1
needs
an
object
whose
synchronized
code
is
being
executed
by
thread1)
and
thread2
is
waiting
for
thread1.
This
situation
is
called
a
Deadlock.
In
a
Deadlock
situation,
both
these
threads
would
wait
for
one
another
for
ever.
Can
you
write
a
synchronized
program
with
wait
and
notify
methods?
package
com.rithus.threads;
class
Calculator
extends
Thread
{
long
sumUptoMillion;
long
sumUptoTenMillion;
public
void
run()
{
synchronized
(this)
{
calculateSumUptoMillion();
notify();
}
calculateSumUptoTenMillion();
}
private
void
calculateSumUptoMillion()
{
for
(int
i
=
0;
i
<
1000000;
i++)
{
sumUptoMillion
+=
i;
}
System.out.println("Million
done");
}
private
void
calculateSumUptoTenMillion()
{
for
(int
i
=
0;
i
<
10000000;
i++)
{
sumUptoTenMillion
+=
i;
}
System.out.println("Ten
Million
done");
}
}
public
class
ThreadWaitAndNotify
{
public
static
void
main(String[]
args)
throws
InterruptedException
{
Calculator
thread
=
new
Calculator();
synchronized(thread){
thread.start();
thread.wait();
}
System.out.println(thread.sumUptoMillion);
}
}
Output
Million
done
499999500000
Ten
Million
done