You are on page 1of 32

Java Synchronization

Mutual Exclusion
• Simultaneous reading and setting of a value
by different threads
• May not be atomic
• One object needs to lock others out until it is
finished
• Can be done at the
1. class level
2. method level
3. on a block of code
The keyword synchronized
• This keyword obtains a mutex (mutual exclusion)
lock for the executing thread on the named
object.
• The code is then executed, and the lock is
released.
• If another object already holds the lock, the
thread is suspended until the lock is released.
• Lock-competing threads are queued.
Java and synchronization
• Java programmers don’t need to do the
low level details of creating, acquiring,
and releasing locks
– Unix semaphores, locks
• Specify the portion of code (critical
section) for mutual exclusion, and the
object that must be exclusively locked
• The region of code must be as small as
possible
Java synchronization techniques

• Mutual Exclusion over an Entire Class

• Object as a lock

• Synchronized blocks of code or methods

– One thread at a time


– While first thread is executing it, others block
Mutual Exclusion over an Entire Class
• Apply the keyword synchronized to a class method.

static synchronized void RaisePressure()

• Only one static synchronized method for a given class can


be running at any given time in the JVM, regardless of
how many objects there are of that class
• the class object (MyClass.class) is used to synchronize the threads
• There is one lock for static synchronized methods, and a
different lock for synchronized methods.
• One thread could have the static lock while another
thread has a method lock, while other threads could be
running other unsynchronized methods
Mutual Exclusion over a Block
• Use the keyword synchronized before a
block of code
• Use a static object for the lock
• Any available, convenient object will do
• Cannot be a local object or instance
variable
Block Mutual Exclusion
class pressure extends Thread
{ static Object lock = new Object();
void raisePressure()
{
synchronized(lock) // Mutex ‘til end
{
if(SetPressure.pressureGauge <

SetPressure.SafetyLimit - 15)
{
...
}
...
}
Object as a Lock
• Any object can serve as a lock
– Separate object: Object myLock = new Object();
– Current instance: the this object

• Enclose lines of code in a synchronized block

synchronized(myLock) {
// code here
}

• More than one thread could try to execute this code,


but one acquires the lock and the others “block” or
wait until the first thread releases the lock
Mutual Exclusion over a Method
• Use synchronized keyword on the instance
method.
• Guarantees that only one of the perhaps
many synchronized instance methods will be
executing at any one time on a given instance
of that class
• Equivalent to synchronized(this) over a block
Synchronized Methods
• Common situation: all the code in a method is a
critical section
– i.e. only one thread at a time should execute that
method
– e.g. a getter or setter or mutator, or something that
changes shared state info (e.g. a Map of important data)

• Java makes it easy: add synchronized keyword to


method signature. e.g.

public synchronized void update(…) {…}


Java Synchonization
Java provides Synchronized keyword to methods that cause
only one invocation of a synchronized method on the same
object at a time.
Example
public class SynchronizedCounter {
private int c = 0;
public synchronized void increment() {
c++;
}
public synchronized void decrement() {
c--;
}
public synchronized int value() {
return c;
}
}
12
Implementation of Java
synchronization
Every object has an intrinsic lock associated with it.

A thread that needs exclusive and consistent access to


an object's fields has to acquire the object's intrinsic lock
before accessing them, and then release the intrinsic lock
when it is done with them.

13
Example using synchronized methods

On-line banking
Several entities can access account potentially simultaneously
(maybe a joint account, maybe automatic debits, …)

Suppose three entities each trying to perform an operation,


either:

• deposit()
• withdraw()
• enquire()

14
Create three threads, one for each entities
class InternetBankingSystem {
public static void main(String [] args ) {
Account accountObject = new Account ();
Thread t1 = new Thread(new MyThread(accountObject));
Thread t2 = new Thread(new YourThread(accountObject));
Thread t3 = new Thread(new HerThread(accountObject));

t1.start();
t2.start();
t3.start();

// DO some other operation

} // end main()
}

15
Shared account
class MyThread implements Runnable {
Account account;
public MyThread (Account s) { account = s;}
public void run() { account.deposit(); }
} // end class MyThread

class YourThread implements Runnable {


Account account;
account
public YourThread (Account s) { account = s;} (shared object)
public void run() { account.withdraw(); }
} // end class YourThread

class HerThread implements Runnable {


Account account;
public HerThread (Account s) { account = s; }
public void run() {account.enquire(); }
} // end class HerThread
16
Synchronized account methods
class Account {
int balance;
// if 'synchronized' is removed, outcome unpredictable

public synchronized void deposit( ) {


balance += deposit_amount;
}

public synchronized void withdraw( ) {


balance -= deposit_amount;
}
public synchronized void enquire( ) {
display balance.
}
}
17
Synchronized Statements
Unlike synchronized methods, synchronized
statements must specify the object that provides the
intrinsic lock:
Evaluate to an
Uses construct ion: object or an
array. Used to
identify lock.
synchronized ( expression ) {

statements “critical section”

}
18
Synchronized Statements

Example

public void addName(String name) {


synchronized(this) {
lastName = name; Only this part
nameCount++; synchronized
}
nameList.add(name);
}

19
atomic action

An atomic action cannot stop in the middle: it either happens


completely, or it doesn't happen at all. No side effects of an
atomic action are visible until the action is complete.

Read/writes can be declared atomic with the volatile keyword,


e.g.

private volatile int x;

Sometimes can be more efficient than synchronized methods.

20
Coordinating threads
Wait/notify mechanism
Sometimes need a thread to stop running and wait for an
event before continuing.

wait() and notify() methods are methods of class Object.

Every object can maintain a list of waiting threads.

wait() When a thread calls wait() method of an object, any


locks the thread holds are temporarily released and
thread added to list of waiting threads for that object
and stops running.
notify() When another thread calls notify() method on the
same object, object wakes up one of the waiting
threads and allows it to continue.
21
Join
Sometimes one thread needs to stop and wait for another
thread to complete.

join() -- waits for a thread to die, i.e. thr1.join() waits for


thread thr1 to die.

Calling return() from the run method implicitly causes the


thread to exit.

22
synchronized Statement
• Every object has a lock associated with it.

• Calling a synchronized method attempts to possess the


lock
– If no one owns the lock, then this thread has/owns the
lock.

• If a calling thread does not own the lock (another thread


already owns it), the calling thread is placed in the entry
set for the object’s lock.

• The lock is released when a thread exits the


synchronized method.
Entry Set
synchronized enter() Method

public synchronized void enter(Object item) {


while (count == BUFFER_SIZE)
Thread.yield();
++count;
buffer[in] = item;
in = (in + 1) % BUFFER_SIZE;
}
synchronized remove() Method
public synchronized Object remove() {
Object item;
while (count == 0)
Thread.yield();
--count;
item = buffer[out];
out = (out + 1) % BUFFER_SIZE;
return item;
}
The wait() Method

• When a thread calls wait(), the following


occurs:
- the thread releases the object lock.
- thread state is set to blocked.
- thread is placed in the wait set.
Entry and Wait Sets
The notify() Method

• When a thread calls notify(), the following


occurs:
- selects an arbitrary thread T from the
wait set.
- moves T to the entry set.
- sets T to Runnable.

T can now compete for the object’s lock


again.
enter() with wait/notify Methods
public synchronized void enter(Object item) {
while (count == BUFFER_SIZE)
try {
wait();
}
catch (InterruptedException e) { }
}
++count;
buffer[in] = item;
in = (in + 1) % BUFFER_SIZE;
notify();
}
remove() with wait/notify Methods
public synchronized Object remove() {
Object item;
while (count == 0)
try {
wait();
}
catch (InterruptedException e) { }
--count;
item = buffer[out];
out = (out + 1) % BUFFER_SIZE;
notify();
return item;
}
Multiple Notifications
• notify() selects an arbitrary thread from the wait
set. *This may not be the thread that you want to
be selected.
• Java does not allow you to specify the thread to
be selected.
• notifyAll() removes ALL threads from the wait set
and places them in the entry set. This allows the
threads to decide among themselves who
should proceed next.
• notifyAll() is a conservative strategy that works
best when multiple threads may be in the wait
set.

You might also like