Java Threads - PowerPoint PPT Presentation

1 / 51
About This Presentation
Title:

Java Threads

Description:

human body, university, car, personal computer, ... Some forms of concurrency in computing ... Dining Philosophers. Coarse-grained Locking ... – PowerPoint PPT presentation

Number of Views:52
Avg rating:3.0/5.0
Slides: 52
Provided by: udokrus
Category:
Tags: java | threads

less

Transcript and Presenter's Notes

Title: Java Threads


1
Java Threads
  • CC438

2
Main Topics
  • Concurrency, processes and threads
  • Defining and running Java threads
  • Thread states, scheduling and termination
  • Interleaving
  • Synchronization
  • Deadlocks
  • Coarse and Fine-Grain Locking
  • Wait and Notify
  • Deprecated thread methods

3
Concurrent Systems
  • A system is concurrent if it can perform several
    activities simultaneously
  • in parallel, at the same time
  • execution of activities can overlap
  • Concurrent systems are everywhere
  • human body, university, car, personal computer,
  • Some forms of concurrency in computing
  • multiple processes on
  • different machines, a multi-processor machine
    (e.g. Dual Core), a single-processor machine
  • different threads within one process
  • Web browser, Web server
  • Real versus apparent (virtual) concurrency

4
Operating System Processes
  • Modern OS like Unix or Windows support multiple
    processes (multitasking)
  • c.f. Windows Task Manager -gt Processes
  • typing java MyProg creates a new process that
    runs MyProg in a JVM.
  • Each process has an independent address space
    processes do not share variables
  • Managed by the operating system
  • OS ensures processes do not interfere
    (isolated)
  • need special mechanisms for communication like
    signals, sockets, remote method invocation
  • Switching processes is relatively slow
  • requires a lot of copying and loading

5
(Java) Threads
  • Lightweight concurrent processing
  • A process can have many threads
  • Each thread is an independent flow of control
  • Threads DO share the same address space
  • so separate threads running in the same process
    can share variables (communication is easy), but
  • threads can also easily disturb each other.
  • Java threads are managed by JVM
  • scheduler activates/deactivates threads
  • switching threads is relatively fast
  • Each program starts with at least one thread
    (main)
  • http//java.sun.com/docs/books/tutorial/essenti
    al/threads/

6
Defining and Running Threads
  • Define class that implements Runnable
  • Runnable has one method void run(). This method
    defines the thread behaviour, equivalent of
    main() method. The thread terminates when run()
    terminates.
  • Construct object of runnable class
  • Construct thread from object
  • Start thread
  • Alternatively, can also obtain Thread objects by
    extending class Thread and overriding run()
  • This approach can save some lines of code.
  • Disadvantage
  • extends Thread, so no other subclassing is
    possible

7
Defining GreetingThread
  • public class GreetingThread implements Runnable
  • private String greeting
  • private static final int REPETITIONS 8
  • private static final int DELAY 100
  • public GreetingThread(String aGreeting)
  • greeting aGreeting
  • public void run()
  • try for (int i 1 i lt REPETITIONS
    i)
  • System.out.println(i " " greeting)
  • Thread.sleep(DELAY)
  • catch (InterruptedException exception)

8
Creating Concurrent GreetingThreads
  • public static void main(String args)
  • Runnable r1 new GreetingThread("Hello,
    World!")
  • Runnable r2 new GreetingThread("Goodbye,
    World!")
  • Thread t1 new Thread(r1)
  • Thread t2 new Thread(r2)
  • t1.start()
  • t2.start()

9
GreetingThread Two Sample Program Runs
1 Hello, World! 1 Goodbye, World! 2 Hello,
World! 2 Goodbye, World! 3 Goodbye, World! 3
Hello, World! 4 Hello, World! 4 Goodbye,
World! 5 Goodbye, World! 5 Hello, World! 6
Hello, World! 6 Goodbye, World! 7 Goodbye,
World! 7 Hello, World! 8 Hello, World! 8
Goodbye, World!
  • 1 Hello, World!
  • 1 Goodbye, World!
  • 2 Hello, World!
  • 2 Goodbye, World!
  • 3 Hello, World!
  • 3 Goodbye, World!
  • 4 Hello, World!
  • 4 Goodbye, World!
  • 5 Hello, World!
  • 5 Goodbye, World!
  • 6 Hello, World!
  • 6 Goodbye, World!
  • 7 Hello, World!
  • 7 Goodbye, World!
  • 8 Goodbye, World!
  • 8 Hello, World!

10
Thread State Diagram Life Cycle
11
Thread States
  • Each thread has a state and a priority
  • Reasons for blocked state (non runnable)
  • sleeping (its sleep() method is invoked)
  • waiting for I/O
  • waiting to acquire a lock
  • waiting for notification
  • Unblocks only if the reason for block goes away
  • in case of sleep() specified time has elapsed
  • in case of I/O I/O has completed
  • in case of waiting for lock acquired lock
  • in case of waiting for notification got
    notification

12
Thread Scheduling
  • Scheduler de-activates a new thread if
  • a thread with higher priority becomes runnable
  • a thread yields because
  • run() method exits, called yield(), has blocked
    itself or
  • for OS with time-sliced threads, it time slice is
    over
  • Scheduler looks only at runnable threads
  • prefers threads with higher priority, also aging
    schemes
  • JVM schedulers try to be fair
  • but on machines without pre-emptive time-slicing
    for threads, a selfish thread could hog the CPU.
  • Ensure balanced progress of threads by doing CPU
    intensive work in small chunks
  • less significant for threads which do lots of
    I/O, or in case of time-slicing for threads.

13
Terminating Threads
  • Thread terminates when run() exits
  • sometimes necessary to terminate a running thread
  • Don't use deprecated stop() method
  • instead interrupt thread by calling interrupt()
  • Thread should cooperate
  • Normally exit after cleaning up
  • Threads should check for interruptions by
  • calling isInterrupted() or
  • performing a sleep/wait and catching
    InterruptedException, see GreetingThread above.
  • Threads are not restartable.
  • Method isAlive() returns true if a thread has
    been started but not terminated.

14
Handling Interrupts in Threads
  • public class MyRunnable implements Runnable
  • public void run() try while (...) //
    do work Thread.sleep(...) catch
    (InterruptedException e) // clean up 

15
Concurrency Interleaving
  • Consider threads t1, t2 with run() methods
    consisting of two atomic statements each
  • t1 public void run() a b
  • t2 public void run() c d
  • Possible execution sequences after starting both
    threads (t1.start() t2.start())
  • (a b c d), (a c b d), (a b d c)
  • (c d a b), (c a d b), (c a b d)
  • All you know is a before b and c before d
  • even that could be wrong due to compiler
    optimizations, see http//www.jcp.org/en/jsr/detai
    l?id133

16
  • public class SharingThread implements Runnable
  • public static int shared
  • public int id
  • static final int REPETITIONS 100000000
  • SharingThread(int id) this.id id
  • public void run()
  • for (int n 1 n lt REPETITIONS n)
  • shared id
  • if (shared ! id)
  • System.out.println("n " n)
  • break

17
Running Concurrent SharingThreads
public static void main(String args)
Thread t1 new Thread(new SharingThread(1))
Thread t2 new Thread(new SharingThread(2)) t
1.start() t2.start()
  • First run n 52344748
  • Second run n 26988321
  • Third run n 15230285
  • ...
  • Seventh run n 24764904

18
Interleaving SharingThread
  • Why is (shared ! id) possible?
  • Because there is nothing that forbids the second
    thread from changing the value of variable shared
    just after it has been set by the first thread,
    and before condition is evaluated
  • SharingThread(1) shared 1
  • SharingThread(2) shared 2
  • SharingThread(1) if (shared ! id)

19
Class CounterThread
public class CounterThread extends Thread
static int total 0 int n public
CounterThread(int n) this.n n
this.start() public void inc()
total public void run() for (int
i 0 i lt n i) inc() public static void
main(String args) throws Exception

20
Creating Concurrent CounterThreads
  • public static void main(String args) throws
    Exception
  • int x Integer.parseInt( args0 )
  • System.out.println( "Running with x " x )
  • ElapsedTimer t new ElapsedTimer()
  • Thread t1 new CounterThread( x )
  • Thread t2 new CounterThread( x )
  • t1.join()
  • t2.join()
  • System.out.println( t " total "
    total )

21
Join
  • t.join() waits for thread t to terminate before
    proceeding
  • t.join(maxTime) waits at most for maxTime ms
  • This is useful when a master thread sends of a
    slave to do some work.
  • see TimeOutReader later
  • In CounterThread.main(), the joins are necessary
    in order to determine how long it has taken until
    both threads are done.

22
Results from CounterThread Runs
  • Running with x 1000000078 ms elapsed total
    20000000
  • Running with x 1000000078 ms elapsed total
    19298155
  • Running with x 1000000078 ms elapsed total
    20000000
  • Running with x 1000000079 ms elapsed total
    20000000
  • Running with x 1000000062 ms elapsed total
    17874631

23
Time-Sliced Thread Interleaving Incrementing a
shared variable

Thread t1
Thread t2
total
0
fetch total
0
fetch total
total
1
total
1
return
1
1
return
1
24
Thread Safety
  • When two or more concurrent threads access a
    common variable potential trouble!
  • problem caused by interleaved reading and writing
    of shared objects, reading on its own is ok
  • so called race conditions
  • Missing atomicity of statements
  • what if one thread yields control when it is
    half-way through updating a shared object?
  • Leads to bad kind of programming errors
  • program works nearly always, errors often only
    show up after a long time/long run
  • Java approach object locks/synchronisation

25
Object Locks and Synchronised Methods
  • Each object has a lock
  • Locks are associated with actual objects, NOT
    with references to objects
  • Threads can lock, unlock object
  • No other thread can lock object until unlocked
  • synchronized is a Java keyword
  • synchronized method locks implicit parameter
  • So no other thread can call another synchronized
    method on the same object
  • provides mutual exclusion for critical code
    that accesses shared resources/ shared variables.
  • Place concurrency-sensitive code regions inside
    synchronized methods
  • public synchronized void myMethod ()

26
Visualizing Locks Horstmann OOPD
  • Object phone booth
  • Thread person
  • Locked object closed booth
  • Blocked thread person waiting for booth to
    open
  • Monitor/lock system that ensures at most one
    person is in the booth at any time

27
Synchronized CounterThread
  • Simply insert the keywords in bold
  • public static synchronized void inc()
  • Now we get the following results
  • Running with x 10000000
  • 4156 ms elapsed total 20000000
  • Running with x 10000000
  • 4952 ms elapsed total 20000000
  • Running with x 10000000
  • 4812 ms elapsed total 20000000

28
Why Static?
  • Without the static modifier, we synchronize on
    instances of the class
  • I.e. we have two locks one for c1 and one for
    c2.
  • Thus there is no contention for the locks, and no
    protection for the static variable total.
  • With the static modifier, the lock is on the
    CounterThread.class object.
  • There is only one of these in the JVM, and the
    static variable total is now properly protected

29
Synchronized Version (x)

Thread t1
Thread t2
total
0
fetch total
1
total
return
1
fetch total
1
total
2
2
return
2
30
Performance of synchronized
  • The code now always returns the correct answer
  • fixing the critical race problem of the incorrect
    version
  • But it is about seven times slower than the
    incorrect, unsynchronized version!
  • Only use synchronization when you need it!
  • When you do need it, be sure to use it!
  • Note method sleep() does not cause a method to
    give up its monitor on an object.

31
Block Synchronization
  • Can also synchronise a block of code by
    associating it with an object that gets
    locked/unlocked.
  • Suppose we have two bank account objects
  • use synchronisation to avoid interference when
    transferring money from one account to another.
  • synchronized (a1)
  • synchronized (a2)
  • a1.transfer( -amount )
    a2.transfer( amount )

32
Block Synchronization (contd)
  • Suppose we now have to book a set of resources
  • Must either book all of them
  • Or none of them
  • Dont know how many in advance
  • Cannot use nesting solution from previous slide
  • Simple iteration does not work e.g.
  • int nFree 0
  • for (Resource r rs)
  • synchronized(r)
  • if (r.free()) nFree
  • Why not?

33
Recursive solution
  • Acquire lock on each resource
  • And then call the same method recursively
  • Until all locks have been obtained
  • boolean allFree(IteratorltResourcegt ir)
  • if (ir.hasNext()) Resource r ir.next()
  • synchronized(r) if (r.free())
  • return allFree(ir) // note recursive
    call else
  • return false
  • else // a realistic example would do
    some action here return true

34
Java Semaphores
  • Directly control access to shared resources
  • java.util.concurrent.Semaphore
  • Usage construct one with the number of
    concurrent accesses allowed (e.g. 1)
  • Semaphore sem new Semaphore(1)
  • To enter the protected zone
  • sem.acquire()
  • When exiting the protected zone
  • sem.release()
  • Offers an alternative to synchronized blocks for
    fine-grained locking.

35
Deadlock (Starvation)
  • Dining philosophers example
  • philosophers sit at a round table
  • eat spaghetti with two forks
  • assume a philosopher first picks up fork to the
    right, then picks up fork to the left, then eats,
    then drops forks
  • what if everyone picks up right fork in parallel
    at start?
  • Deadlock situation with two threads/locks
  • Thread 1 acquires lock on object A
  • Thread 2 acquires lock on object B
  • Thread 1 waits for lock on object B
  • Thread 2 waits for lock on object A
  • Deadlock avoidance
  • ensure deadlocks are impossible

36
Coarse-grained Locking
  • A thread obtains the lock (the bold outline) on
    an entire set of resource objects
  • This locks out any other thread from accessing
    any of the objects in the set.
  • Little danger of deadlock.
  • Potentially inefficient if threads could do some
    work independently
  • for example, one thread could do computations
    while another waits for file download.

Res. 1
Res. 2
Res. 3
Res. n
37
Fine-grained Locking
  • A thread just obtains the locks on the particular
    objects it needs for a transaction
  • Potentially more efficient than coarse-grained
    whenever concurrent work is possible
  • less blocking of threads
  • More danger of deadlock due to individual locks.
  • Q is deadlock possible for synchronized
    CountTimer.inc() ?

Res. 1
Res. 2
Res. 3
Res. n
38
Dining Philosophers

39
Coarse-grained Locking
  • Implementing a coarse-grained locking strategy
    for the dining philosophers is straightforward
  • The synchronization is done on the entire set of
    chopsticks
  • so at most one philosopher can access chopsticks
  • This prevents deadlock
  • But as we can see from running the applet, it
    makes for slow eating
  • if we interpret the philosophers as computational
    resources and eating as doing work, then at
    most one resource is actually working at any
    given time.

40
Fine-grained Locking
  • Now we lock at the chopstick level i.e. at
    individual resource level
  • the synchronisation ensures that no two
    philosophers can pick up one chopstick at the
    same time
  • BUT need to be careful about how we request the
    locks
  • Otherwise, could end up in a state of deadlock
  • Simple deadlock avoidance strategy
  • restrict order of requests
  • philosopher 1 takes right fork first, then left
    forkall other philosophers take left fork
    first, then right fork
  • other strategies are possible

41
wait, notify, notifyAll
  • Given an Object obj
  • obj.wait() causes the current thread to wait
    until
  • another thread calls obj.notify() or
    obj.notifyAll().
  • These methods can only be called by a thread that
    owns the monitor on this object.
  • a thread acquires the monitor on an object by
    entering a synchronized method/block on that
    object.
  • A waiting thread is blocked until it is notified.
  • notifyAll() unblocks all threads waiting on this
    object
  • wait(long timeout) waits specified time for
    notification
  • if no notification has arrived within time, then
    the thread tries to regain monitor on object.

42
Using wait and notify
  • Support for communication between threads
  • For example consider a program that waits for
    user input before proceeding
  • Lets look at two examples
  • first a command line version
  • then the GUI version using a PauseButton

43
Command-line PauseIO
  • package cc438.exercises
  • public class PauseIO
  • public static void main(String args) throws
    Exception
  • System.out.println("Press ltentergt to
    continue")
  • System.in.read()
  • System.out.println("Thank you for
    continuing")

44
Using a PauseButton
  • public static void main(String args) throws
    Exception
  • PauseButton pauser new PauseButton()
  • new JEasyFrame( pauser, "Click to
    proceed", false )
  • pauser.pause()
  • System.out.println("Thank you for
    continuing")

45
  • // package and import omitted
  • public class PauseButton extends Button
  • implements ActionListener
  • public PauseButton() // this labels the
    Button
  • super("Click to proceed")
  • addActionListener( this )
  • public synchronized void pause() throws
    Exception
  • wait()
  • public synchronized void actionPerformed(
    ActionEvent e)
  • System.out.println("Button Clicked")
  • notifyAll()
  • C\srcgt\jdk5\bin\java test.PauseGui
  • Button Clicked

46
How the PauseButton Code Works
  • After creating a PauseButton, it gets added as a
    component to a Frame
  • JEasyFrame is just a convenient subclass of Frame
  • we then call the pause() method on the Button
  • The PauseButton class extends java.awt.Button
  • The wait() and notify() calls are performed in
    synchronized methods of PauseButton
  • pause() calls wait()
  • notifyAll() is called by the GUI thread in
    response to a user clicking the button.

47
Thread Priorities
  • Each thread has a priority, ranging between
    MIN_PRIORITY (1) and MAX_PRIORITY(10)
  • By default, each new thread has the same priority
    as the one that started it.
  • The initial thread associated with main() by
    default has priority Thread.NORM_PRIORITY(5)
  • Priorities affect how threads in the runnable
    state are activated for running.
  • Priorities can be used for tweaking performance
  • improve responsiveness of program
  • Programs should not rely on priorities for
    running correctly.

48
Thread Performance
  • Several overheads to consider
  • Thread creation / destruction
  • The cost of creating and destroying threads
  • Thread load
  • How many threads can run concurrently before
    running out of memory?
  • Synchronization
  • The cost of acquiring / releasing object locks
  • Thread activation
  • Cost of stopping / starting threads

49
Daemon threads
  • Normally created threads are called user threads.
  • Method setDaemon(boolean on) marks
  • a daemon thread (ontrue) or a user thread (on
    false).
  • this method must be called before the thread is
    started.
  • by default, a child thread inherit parent daemon
    status.
  • Daemon threads are supposed to be servants to
    user threads, so the JVM exits when the only
    threads still alive are daemon threads.
  • this will terminate all the daemon threads
  • Example GUI event threads are daemon threads
  • Feature not all that useful but can save some
    manual thread termination code.

50
Deprecated Thread Methods
  • Thread.stop() was deprecated as stopping a thread
    causes it to unlock all monitors that it has
    locked.
  • danger of inconsistent program states unless
    programs keep checking for stopped threads
    (impractical)
  • Thread.suspend() and Thread.resume() were
    deprecated as they are very deadlock prone.
  • resource blocks if suspended thread holds lock
  • Use deprecated methods at your peril!!
  • Instead of stop(), prefer interrupt()
  • let the thread decide how to react to an
    interrupt
  • Instead of suspend() /resume(), use
    wait()/notify().
  • Further details at http//java.sun.com/j2se/1.5.0
    /docs /guide/misc/threadPrimitiveDeprecation.html

51
Thread Summary
  • Java provides straightforward ways to write
    multithreaded programs
  • implements Runnable, or extends Thread
  • Thread work done within its run() method
  • Keyword synchronized to lock methods or blocks
    of code
  • wait() and notify(), notifyAll() to communicate
    between blocking threads (see PauseGui)
  • t.join() used to wait for the death of thread t
Write a Comment
User Comments (0)
About PowerShow.com