Title: Concurrency in Java
1Concurrency in Java
- Create threads in Java
- Explain priorities priority inversion
- Use class and object locks (synchronized)
- Synchronized methods
- Synchronized statements
- Explain the monitor concept
- Use sleep(), wait(), notify() and notifyAll()
2Reading
- SUN tutorial
- http//java.sun.com/docs/books/tutorial/essential/
concurrency/index.html - SUN Tech Tip
- http//java.sun.com/developer/TechTips/2000/tt0328
.html
3What is a Thread?
- Part of a program that can run in parallel with
other program parts - Multiple processors
- A section at a time on a single processor
- Share instance variables
- Not local variables
- A class with a run() method
- A direct descendant of Thread overriding run()
- A Thread passed a class implementing Runnable
- Which means that class provides a run() method
4The life of a thread
finished
running
blocked
created
ready
5Priority
- Threads inherit the creators priority
- getPriority(), setPriority()
- MIN_PRIORITY .. MAX_PRIORITY
- Threads with higher priority have preference
- Priority Inversion
- Low priority task holds shared resource
- Resource required by a high priority task
- Medium priority task blocks both
6Creating, Starting Awaiting Death
- public class IncrementTest implements Runnable
- static int numThreads 10
- static int value0
- static int numInc 14000000
- static Thread threads
-
- public static void main(String args)
- System.out.println("Program Starting")
- threads new ThreadnumThreads
- for (int n0 nltnumThreads n)
- threadsn new Thread(new
IncrementTest()) - threadsn.setPriority(1
(int)(Math.random()4)) - threadsn.start()
-
- System.out.println("Waiting for threads
to terminate") - for (int n0 nltnumThreads n)
- try
7Thread Body
- public void run()
- int val
-
- for (int i 0 i lt numInc i)
- val value
- val val 1
- value val
-
-
- value value - numInc
-
What is the overall effect of this task?
In theory, it does nothing Increments value
numInc times Then subtracts numInc
8Overview
Main Method
Copy Value
Increment Locally
Write back
Create Start
Wait For Tasks To Die
Copy Value
Increment Locally
Write back
Two increments but value changed by one
Value 0
Value 1
9The Problem
value 6
Thread 1 val value val val
1 value val
Thread 2 val value val val 1 value
val
value is a shared static variable
value 7
10You think Itll never happen to me
- Youd write
- value value numInc
- Bad news
- this generates several machine instructions e.g.
- MOV register, value
- Add register, numInc
- MOV value, register
- Threads may be switched between instructions
- Time-slicing
- A higher priority waiting thread becomes ready
11I still dont believe you
- Instance variables are shared by threads
- One thread can modify a variable
- Will another thread see the new value
- The compiler can optimize variable access
- Caching values into registers
- Other threads can see old values
- When writing a variable that may be read by
another thread, or reading a variable that may
have been written by another thread, you must
synchronize.
12Java Solution synchronize
- synchronize uses a lock on an object
- Only one thread can hold the lock
- Other threads are suspended until it is released
- synchronized statements
- synchronized (anObject)
- // various statements
-
- Lock on anObject
- Only one section locked on an object can be in
execution at any one time
13Solution 1 synchronized statement
- public void run()
- synchronized(threads)
-
- int val
-
- for (int i 0 i lt numInc i)
-
- val value
- val val 1
- value val
-
- value value - numInc
-
14Example Output
15Sychronized Methods
- class newObject
- synchronized myMethod()
- synchronized myMethod2()
- static synchronized staticMet()
-
- myMethod() - lock on an instance of the class
- myMethod() myMethod2() on a single object
- are mutually exclusive
- Separate threads can call myMethod on different
objects at the same time - staticMet() lock on a class
- Only one thread can execute staticMet at once
16Solution 2 synchronized method
- static synchronized public void inc()
- int val
- for (int i 0 i lt numInc i)
- val value
- val val 1
- value val
-
- value value - numInc
-
- public void run()
- inc ()
Otherwise each thread has its own lock
Why must this method be static?
17Producer-Consumer Problem
- A common situation
- Producers pass data to consumers
- Using a buffer (Why?)
- Issues
- Must ensure mutual exclusion on buffer
- Only one thread can manipulate data structures
- Must wait for space to be available
- If producers are faster than consumers
- Must wait for items to be available
- If consumers are faster than producers
Buffers allow for varying speeds
18Java Solution Buffer Class
Producer
Consumer
insert
extract
Consumer
Producer
- synchronized methods insert() extract()
- Guarantees mutual exclusion
- But problems waiting for items / space
- Cant wait inside exclusion zone
- No other thread can get in to add / remove items
- Cant wait outside exclusion zone
- Another thread might grab lock first
19Solution wait()/notifyAll()
- public void insert(String item)
- while (available body.length)
- try
- wait()
- catch(InterruptedException e)
-
- // Insert item increment available
-
- notifyAll()
Suspends this thread and releases the lock
Releases all threads suspended on this lock. They
cannot proceed until this thread releases the
lock.
Why not use notify()? More efficient wakes up
just 1 thread, but ...
20Other Thread Methods
- sleep(long milliseconds)
- Suspend the task for a fixed period
- Unless interrupted
- Keeps hold of the monitors
- interrupt()
- Interrupt the task stops wait, sleep
- join()
- Wait for the thread to finish
- suspend() / stop()
- Deprecated
- may deadlock if thread holds a lock
21Stopping a task
- volatile int finished
- setDone()
- finished true
- this.interrupt()
-
- run()
- while (!finished)
- // do things
- try
- sleep()
- catch(InterruptedException e)
- continue
-
-
- Stopping the thread
- theThread.setDone()
- Advantages
- Allows the thread to tidy up
- Problems
- The thread may not stop immediately
22Summary
- Java provides mutual exclusion through
- Synchronized statement
- Synchronized method
- General synchronisation is provided through
- wait()
- notify()
- notifyAll()
- Dont stop a task directly
- Give it chance to tidy up free locks resources