• Embed Doc
  • Readcast
  • Collections
  • 1
    CommentGo Back
Download
 
12
MARCH 2008
|
LINUX FoR YoU
|
 www.penITis.cm
c m yk
M
ulti-threading
Let’s get the basics of multi-threaded programming in Java, andthen write some simple programs.
Overview
An Introduction to
 
www.penITis.cm
|
LINUX FoR YoU
|
MARCH 2008
c m yk
13
Overview
I
n a typical application like a wordprocessor, many tasks need to be executedin parallel—or instance, responding tothe user, checking spellings, ormatting,displaying, saving, etc. These tasks canrun as dierent processes, sharing the resourcesusing inter-process communication. Multi-processingis heavyweight and costly in terms o the system callsmade, and requires a process switch. An easier and cheaper alternative is to use threads.Multiple threads can run in the context o the sameprocess and hence share the same resources. A contextswitch is enough to switch between threads, whereas acostly process switch is needed or processes.Java has support or concurrent programming andhas support or multi-threading in both language andlibrary levels. In this article, we’ll cover the basics o multi-threaded programming in Java and write somesimple programs. We’ll also look at some dicultproblems that can crop up when we write multi-threaded code.
The basics
 A Java thread can be created in two ways: byimplementing the
 Runnable
interace or by extendingthe
Thread
class. Both have a method called
run
. Thismethod will be called by the runtime when a threadstarts executing. A thread can be created by invoking the start methodon a
Thread
or its derived objects. This in turn calls therun method and keeps the thread in running state. Nowlet us look at a simple example using threads.
class MyThread extends Thread {public void run() {System.out.println(“This is new thread”);}public static void main(String args[]) throws Exception {MyThread mt = new MyThread();mt.start();System.out.println(“This is the main Thread”);}}
This program prints:
This is the main ThreadThis is new thread
In this example, the
 MyThread
class extends the
Thread
class. We need to override the run methodin this class. This run method will be called when thethread runs. In the main unction, we create a newthread and start it. The program prints messagesrom both the main thread and the mt thread (that wecreated in
 main
).
Asynchronous execution
Note that created threads run ‘asynchronously’. Thismeans that threads do not run sequentially (like unctioncalls); rather, the order o execution o threads is notpredictable. To understand this, let us extend our simpleprogram here: 
class MyThread extends Thread {public void loop() {for(int i = 0; i < 3; i++) {System.out.println(“In thread “ +Thread.currentThread().getName() +“; iteration “ + i);try {Thread.sleep((int)Math.random());}catch(InterruptedException ie) {ie.printStackTrace();}}}public void run() {System.out.println(“This is new thread”);this.loop();}public static void main(String args[]) throws Exception {MyThread mt = new MyThread();mt.start();System.out.println(“This is the main Thread”);mt.loop();}}
In a sample run, the output was:
This is the main ThreadIn thread main; iteration 0This is new threadIn thread Thread-0; iteration 0In thread Thread-0; iteration 1In thread main; iteration 1In thread Thread-0; iteration 2In thread main; iteration 2
In this program, we have a loop method that has a
 for
 loop that has three iterations. In the
 for
loop, we printthe name o the thread and the iteration number. We canset and get the name o the thread using
 setName
and
 getName
methods, respectively. I we haven’t set thename o the thread explicitly, the JVM gives a deaultname (‘main’, ‘Thread-0’, ‘Thread-1’, etc.). Ater printingthis inormation, we orce the current thread to sleep or
 
14
MARCH 2008
|
LINUX FoR YoU
|
 www.penITis.cm
c m yk
Overview
10 milli-seconds.The main thread (‘main’) and the child thread(‘hread-0’) are executed independently. The outputis not xed and the order o executing the iterationsin the threads is not predictable. This is one o theundamental and important concepts to understand inmulti-threading.
Data races
Threads share memory and they can concurrentlymodiy data. This can lead to unintuitive results and endin ‘data races’. Here is an example o a data race:
class Counter {public static long count = 0;}class UseCounter implements Runnable {public void run() {for (int i = 0; i < 3; i++) {Counter.count++;System.out.print(Counter.count + “);}}}public class DataRace {public static void main(String args[]) {UseCounter c = new UseCounter();Thread t1 = new Thread(c);Thread t2 = new Thread(c);Thread t3 = new Thread(c);t1.start();t2.start();t3.start();}}
In this program, we have a
Counter
class, which hasa static variable count. The
UseCounter
class simplyincrements the count and prints the count three times ina
 for
loop. We create three threads in the main unctionin the
 DataRace
class and start it. We expect theprogram to print 1 to 9 sequentially as the threads runand increment the counters. However, when we run thisprogram, it does print 9 integer values, but the outputlooks like garbage! In a sample run, I got these values:
3 3 5 6 3 7 8 4 9
Note that the values will usually be dierent everytime you run this program. What is the problem?The expression
Counter.count++
is a writeoperation and the next
 System.out.print
statementhas a read operation or
Counter.count
. When thethree threads execute, each o them has a local copyo the value
Counter.count
and when they updatethe counter with
Counter.count++
, they need notimmediately refect that value in the main memory. Inthe next read operation o 
Counter.count
, the local value o 
Counter.count
is printed.Technically, this program has a ‘data race’. To avoidthis problem, we need to ensure that the write andread operations are done together (‘atomically’) by asingle thread. How do we ensure that? It is by acquiringa lock on the object. Only a single thread can acquirea lock on an object at a time, and only that threadcan execute the code protected by the lock (thatcode segment is known as a ‘critical section’). Untilthen the other threads have to wait. Internally, this isimplemented with monitors and the process is called aslocking and unlocking.
Thread synchronisation
Java has a keyword synchronised to acquire a lock. Lockis not obtained on code, but on a resource. Any object(not primitive types but o reerence type) can be usedto acquire a lock.Here is an improved version o the code that providessynchronised access to
Counter.count
, and does bothread and write operations on that in a critical section.For that, only the run method needs to be changed asollows:
public void run() {for (int i = 0; i < 3; i++) {synchronized(this) {Counter.count++;System.out.print(Counter.count + “);}}}
The program now prints the expected outputcorrectly:
1 2 3 4 5 6 7 8 9
In the run method, we acquire lock on the implicitthis pointer beore doing both reading and writing to
Counter.count.
In this case, run is a non-static method. What aboutstatic methods, as they do not have this pointer? Youcan obtain a lock or a static method, and the lock isobtained or the class instance and not the object. In act,in this example,
Counter.count
is a static member, so wemight as well have acquired a lock on
Counter.class
ormodiying and reading
Counter.count
.
Deadlocks
Obtaining and using locks is tricky and can lead to lotso problems, one o which (a common one) is known as
of 00

Leave a Comment

You must be to leave a comment.
Submit
Characters: ...
07 / 12 / 2010This doucment made it onto the Rising List!
You must be to leave a comment.
Submit
Characters: ...