Download presentation
Presentation is loading. Please wait.
Published byKelley McCarthy Modified over 9 years ago
1
Threading and Concurrency Issues ● Creating Threads ● In Java ● Subclassing Thread ● Implementing Runnable ● Synchronization ● Immutable ● Synchronized Methods ● Synchronized Blocks ● Performance Issues ● Thread Pooling ● Transactions and Threading ● Thread safety issues ● Thread-safe ● Immutable ● Thread-hostile
2
Creating Threads ● In Java, there are two options: ● Subclass the Thread class ● Implement Runnable ● Subclassing is usually the poorest choice because you force the threaded class into an inheritance hierarchy. ● The most flexible solution is to implement Runnable.
3
Thread1 Thread Object start() Thread2 run() public class Test extends Thread { // The start method is defined in the // Thread class. When called, it creates // a new thread and the new thread invokes // “run” on the current object public void run() { // This method runs in its // own thread } Subclassing Thread
4
Runnable Object public class Test implements Runnable { private Thread theThread; public void start() { if (theThread == null) { theThread = new Thread(this); theThread.start(); } public void run() { // This method runs in its // own thread } Thread1 Thread Object start() Thread2 run() start() Thread(Runnable) Implementing Runnable create
5
Terminating Threads ● When Java was first introduced, the multi-threading library offered a method called stop(). ● This method was invoked to stop a thread. ● However, it turned out that use of the stop method could lead to deadlock conditions ● When the stop method was invoked the thread would stop immediately and it wasn't given the opportunity to release any resources that it held. ● Uncontrolled stopping of a thread would give rise to unsafe conditions. ● The correct way to terminate a thread is for the thread to return from the “run” method ● This is usually accomplished through setting a boolean variable which is periodically checked within the run method.
6
public class Test implements Runnable { private Thread theThread; private boolean stopThread = false; public void start() { if (theThread == null) { theThread = new Thread(this); theThread.start(); } public void setStopThread(boolean aValue) { stopThread = aValue; } public void run() { while(!stopThread) { //... } Terminating Threads
7
Synchronization ● As you learned in CPSC 457, multi-threaded applications are subject to concurrency problems ● When two threads attempt to update the same data at the same time, the execution of the threads can become interleaved which gives rise to race conditions ● Race conditions can cause erroneous results in computation ● To prevent corruption, the programmer must identify shared variables. ● Access to these variables must be mutually exclusive in time between threads ● ie. only one thread may update a shared variable at any given point in time ● Java provides a “synchronized” keyword which is used to guarantee mututal exclusion in time.
8
Object monitors ● In order to accomplish mutual exclusion, each object in java is provided with a monitor (or lock). ● The lock cannot be directly accessed, it can only be access through the use of the synchronized keyword. ● If a method or block is synchronized, then a thread may not enter the method or block until it has obtained the monitor. ● If a thread cannot obtain the lock for the given method or block, it becomes blocked by the scheduler until such time that the monitor becomes available ● The testing and setting of the monitor is guaranteed to be atomic.
9
Synchronized methods ● The easiest way of obtaining mutual exclusion in Java is by defining methods as synchronized. ● If a method is synchronized, the monitor of the target object is obtained. ● It is possible to define multiple synchronized methods within a class. ● This guarantees that only one thread may be executing any of the synchronized methods at a give point in time. public class SavingsAccount { private float balance; public synchronized void withdraw(float anAmount) { if ((anAmount>0.0) && (anAmount<=balance)) balance = balance - anAmount; } public synchronized void deposit(float anAmount) { if (anAmount>0.0) balance = balance + anAmount; }
10
Synchronization and performance ● Unfortunately, synchronization comes with a price. ● Performance suffers because threads which could be executing are blocked if another thread is currently executing a synchronized method on the target object. ● The solution to this problem is to make the area which is synchronized as small as possible ● Methods do not offer fine enough granularity. ● It is possible to synchronize blocks instead of whole methods.
11
Synchronized blocks public class SavingsAccount { private float balance; public void withdraw(float anAmount) { if (anAmount<0.0) throw new IllegalArgumentException("Withdraw amount negative"); synchronized(this) { if (anAmount<=balance) balance = balance - anAmount; } public void deposit(float anAmount) { if (anAmount<0.0) throw new IllegalArgumentException("Deposit amount negative"); synchronized(this) { balance = balance + anAmount; }
12
Synchronized blocks and methods: ● This method: is equivalent to this method: public synchronized void withdraw(float anAmount) { if ((anAmount>0.0) && (anAmount<=balance)) balance = balance - anAmount; } public void withdraw(float anAmount) { synchronized(this) { if ((anAmount>0.0) && (anAmount<=balance)) balance = balance – anAmount; }
13
Other performance considerations ● While the creation of threads is a relatively inexpensive operation (particularly when compared to creating processes), there is still an overhead should an application be creating and terminating a large number of threads. ● One general solution is to create a thread pool: ● References to the Runnable objects are kept in a collection and pulled out when needed ● Runnable objects obtain their work (in the form of transactions) from a queue. If no work is available, the thread blocks.
14
General Threading Considerations ● Avoid over-synchronization ● Don't write code which depends on how the scheduler is going to behave ● Always invoke wait within a loop ● Never use thread groups ● Never use stop() or resume() ● Document Thread Safety ● Immutable: Data cannot change. No external synchronization is necessary ● Thread-safe: instance of the class are mutable, but the methods contain sufficient internal synchronization so that the methods can be used without any external synchronization ● Conditionally thread-safe: Some methods must be invoked in a specific order or external synchronization must be provided. ● Thread-compatible: Instances can be used concurrently provided that each method is protected by external synchronization ● Thread-hostile: cannot be used concurrently, even if external synchronization is provided.
Similar presentations
© 2024 SlidePlayer.com. Inc.
All rights reserved.