Info 408 Distributed Applications programming 2 nd semester of 2017/2018 Credits: 5 Lecturer: Dr. Antoun Yaacoub

Similar documents
Multitasking Multitasking allows several activities to occur concurrently on the computer. A distinction is usually made between: Process-based multit

Java Threads. COMP 585 Noteset #2 1

Info 408 Distributed Applications Programming Exercise sheet nb. 4

CMSC 132: Object-Oriented Programming II. Threads in Java

Threads and Parallelism in Java

Computation Abstractions. Processes vs. Threads. So, What Is a Thread? CMSC 433 Programming Language Technologies and Paradigms Spring 2007

Java Threads. Written by John Bell for CS 342, Spring 2018

27/04/2012. We re going to build Multithreading Application. Objectives. MultiThreading. Multithreading Applications. What are Threads?

Multiple Inheritance. Computer object can be viewed as

Chapter 32 Multithreading and Parallel Programming

Advanced Java Programming Course. MultiThreading. By Võ Văn Hải Faculty of Information Technologies Industrial University of Ho Chi Minh City

Java s Implementation of Concurrency, and how to use it in our applications.

Object Oriented Programming. Week 10 Part 1 Threads

CS 2112 Lecture 20 Synchronization 5 April 2012 Lecturer: Andrew Myers

What is a thread anyway?

Performance Throughput Utilization of system resources

MultiThreading 07/01/2013. Session objectives. Introduction. Introduction. Advanced Java Programming Course

Contents. 6-1 Copyright (c) N. Afshartous

JAVA and J2EE UNIT - 4 Multithreaded Programming And Event Handling

CS11 Java. Fall Lecture 7

Programmazione Avanzata e Paradigmi Ingegneria e Scienze Informatiche - UNIBO a.a 2013/2014 Lecturer: Alessandro Ricci

Threads Questions Important Questions

Animation Part 2: MoveableShape interface & Multithreading

Programming Language Concepts: Lecture 11

Info 408 Distributed Applications programming 2 nd semester of 2017/2018 Credits: 5 Lecturer: Dr. Antoun Yaacoub

Concurrent Programming using Threads

CMSC 433 Programming Language Technologies and Paradigms. Concurrency

Introduction to Java Threads

Need for synchronization: If threads comprise parts of our software systems, then they must communicate.

Synchronized Methods of Old Versions of Java

CMSC 330: Organization of Programming Languages. Threads Classic Concurrency Problems

Graphical Interface and Application (I3305) Semester: 1 Academic Year: 2017/2018 Dr Antoun Yaacoub

Shared-Memory and Multithread Programming

Producing Production Quality Software. Lecture 12: Concurrent and Distributed Programming Prof. Arthur P. Goldberg Fall, 2004

CMSC 330: Organization of Programming Languages

Concurrency in Java Prof. Stephen A. Edwards

Multi-threading in Java. Jeff HUANG

Chapter 19 Multithreading

CS 351 Design of Large Programs Threads and Concurrency

Unit III Rupali Sherekar 2017

UNIT V CONCURRENT PROGRAMMING

Informatica 3. Marcello Restelli. Laurea in Ingegneria Informatica Politecnico di Milano 9/15/07 10/29/07

Software Practice 1 - Multithreading

CS 6456 OBJCET ORIENTED PROGRAMMING IV SEMESTER/EEE

Multithread Computing

Unit - IV Multi-Threading

THREADS AND CONCURRENCY

Java Threads. Introduction to Java Threads

G Programming Languages Spring 2010 Lecture 13. Robert Grimm, New York University

CS 159: Parallel Processing

Quiz on Tuesday April 13. CS 361 Concurrent programming Drexel University Fall 2004 Lecture 4. Java facts and questions. Things to try in Java

7. MULTITHREDED PROGRAMMING

Principles of Software Construction: Concurrency, Part 2

Get Unique study materials from

Java Programming Lecture 23

Synchronization SPL/2010 SPL/20 1

Unit 4. Thread class & Runnable Interface. Inter Thread Communication

Only one thread can own a specific monitor

Lecture 9: Introduction to Monitors

Modern Programming Languages. Lecture Java Programming Language. An Introduction

Definition: A thread is a single sequential flow of control within a program.

The Dining Philosophers Problem CMSC 330: Organization of Programming Languages

Multithreaded Programming

Techniques of Java Programming: Concurrent Programming in Java

Threads. Definitions. Process Creation. Process. Thread Example. Thread. From Volume II

CMSC 330: Organization of Programming Languages. The Dining Philosophers Problem

3.Constructors and Destructors. Develop cpp program to implement constructor and destructor.

Robotics and Autonomous Systems

Threads in Java (Deitel & Deitel)

Lecture 20. Java Exceptional Event Handling. Dr. Martin O Connor CA166

THREADS AND MULTITASKING ROBOTS

ROBOTICS AND AUTONOMOUS SYSTEMS

CmpSci 187: Programming with Data Structures Spring 2015

Component-Based Software Engineering

G51PGP Programming Paradigms. Lecture 009 Concurrency, exceptions

CS211 Lecture: Concurrency, Threads; UML Activity Diagrams last revised October 11, 2007 Objectives

Problems with Concurrency. February 19, 2014

CS455: Introduction to Distributed Systems [Spring 2019] Dept. Of Computer Science, Colorado State University

Shared Objects & Mutual Exclusion

Chair of Software Engineering. Java and C# in depth. Carlo A. Furia, Marco Piccioni, Bertrand Meyer. Java: concurrency

Synchronization in Concurrent Programming. Amit Gupta

CST242 Concurrency Page 1

Monitors; Software Transactional Memory

Contribution:javaMultithreading Multithreading Prof. Dr. Ralf Lämmel Universität Koblenz-Landau Software Languages Team

JAVA CONCURRENCY FRAMEWORK. Kaushik Kanetkar

Threads Chate Patanothai

Java Monitors. Parallel and Distributed Computing. Department of Computer Science and Engineering (DEI) Instituto Superior Técnico.

Concurrency & Parallelism. Threads, Concurrency, and Parallelism. Multicore Processors 11/7/17

Concurrent Programming. Copyright 2017 by Robert M. Dondero, Ph.D. Princeton University

CS211 Lecture: Concurrency, Threads; UML Activity Diagrams last revised October 5, 2009 Objectives

Thread Programming. Comp-303 : Programming Techniques Lecture 11. Alexandre Denault Computer Science McGill University Winter 2004

CS 556 Distributed Systems

Java for Programmers Course (equivalent to SL 275) 36 Contact Hours

Threads, Concurrency, and Parallelism

Overview. Processes vs. Threads. Computation Abstractions. CMSC 433, Fall Michael Hicks 1

Chapter 1 GETTING STARTED. SYS-ED/ Computer Education Techniques, Inc.

Synchronization in Java

THREADS & CONCURRENCY

MVP1: Introduction to concurrency in JAVA

JThreads/C++ Version 2.0.0b1. IONA Technologies PLC

Transcription:

Lebanese University Faculty of Sciences I Master 1 degree Computer Sciences Info 408 Distributed Applications programming 2 nd semester of 2017/2018 Credits: 5 Lecturer: Dr. Antoun Yaacoub

2 Multithreading Chapter VI

Objectives 1. understand what is meant by a thread (in a programming context); 2. appreciate the need for multithreaded programming; 3. be aware of typical circumstances under which multithreading might be appropriate; 4. know how to implement threads in Java; 5. know how to implement variable locking in Java; 6. be aware of the danger posed by deadlock; 7. know what Java methods to use in order to improve thread efficiency and reduce the likelihood of deadlock; 8. know how to implement a multithreaded server. 3

Introduction It is often the case nowadays that programs need to carry out more than one significant task at the same time (i.e., concurrently ). For example: a GUI-driven program may be displaying a background animation while processing the user s foreground interactions with the interface, or a Web browser may need to download and display the contents of a graphics file while rendering the rest of the associated Web page. The popularity of client/server applications over the past decade has exacerbated this demand enormously, with server programs sometimes having to process the needs of several hundreds of clients at the same time. 4

Introduction Not many years ago, each client that connected to a server would have caused a new process to be spawned on the server. The problem with this approach is that a fresh block of memory is set aside for each such process. While the number of clients connecting to the server remained reasonably low, this presented no difficulties. However, as the use of the Internet mushroomed, servers that created a new process for each client would grind to a halt as hundreds, possibly thousands, of clients attempted to access their services simultaneously. A way of significantly alleviating this problem is to use what are called threads, instead of processes. Though the use of threads cannot guarantee that a server will not crash, it greatly reduces the likelihood of it happening by significantly increasing the number of client programs that can be handled concurrently. 5

Thread Basics A thread is a flow of control through a program. Unlike a process, a thread does not have a separate allocation of memory, but shares memory with other threads created by the same application. This means that servers using threads do not exhaust their supply of available memory and collapse under the weight of excessive demand from clients, as they were prone to do when creating many separate processes. In addition, the threads created by an application can share global variables, which is often highly desirable. This does not prevent each thread from having its own local variables, of course, since it will still have its own stack for such variables. 6

Thread Basics Though it has been entirely transparent to us and we have had to make no explicit programming allowance for it, we have already been making use of threads in our Java programming. In fact, we cannot avoid using threads in Java, since each program will have at least one thread that is launched automatically by our machine s JVM when that program is executed. Such a thread is created when main is started and killed when main terminates. If we wish to make use of further threads, in order to offload processing tasks onto them, then we have to program such threads explicitly. Using more than one thread in this way is called multithreading. 7

8 Threads Execution Thread 1 Thread 2 Thread 3 Thread 4

Thread States Diagram When a thread is created, it is in the New state until the start() method is invoked - the thread becomes Runnable/Ready. The scheduler - and only the scheduler - picks one or more threads that can execute code, by doing this it makes the threads Running. It is also the scheduler that stops a running thread and puts it in the Runnable/Ready state to give each thread a fair amount of running time. The thread can call the yield() method which signals to the scheduler the thread is willing to be Runnable/Ready and let other threads run instead. A thread can die when the run method completes. There is no external switch to kill off a thread. Well, there is the deprecated stop method, but that should never be used. 9

Using Threads in Java Java is unique amongst popular programming languages in making multithreading directly accessible to the programmer, without him/her having to go through an operating system API. Unfortunately, writing multithreaded programs can be rather tricky and there are certain pitfalls that need to be avoided. These pitfalls are caused principally by the need to coordinate the activities of the various threads, as will be seen in a while. 10

Using Threads in Java In Java, an object can be run as a thread if it implements the inbuilt interface Runnable, which has just one method: run. Thus, in order to implement the interface, we simply have to provide a definition for method run. Since the inbuilt class Thread implements this interface, there are two fundamental methods for creating a thread class: create a class that extends Thread; create a class that does not extend Thread and SPECIFY EXPLICITLY that it implements Runnable. Of course, if the application class already has a superclass (other than Object), extending Thread is not an option, since Java does not support multiple inheritance. 11

Using Threads in Java 1. Extending the Thread Class 2. Explicitly Implementing the Runnable Interface 12

Extending the Thread Class The run method specifies the actions that a thread is to execute and serves the same purpose for the process running on the thread as method main does for a full application program. Like main, run may not be called directly. The containing program calls the start method (inherited from class Thread), which then automatically calls run. Class Thread has seven constructors, the two most common of which are: Thread() Thread(String<name>) The second of these provides a name for the thread via its argument. If the first is used, the system generates a name of the form Thread-n, where n is an integer starting at zero and increasing in value for further threads. Thus, if three threads are created via the first constructor, they will have names Thread-0, Thread-1 and Thread-2 respectively. Whichever constructor is used, method getname may be used to retrieve the name. 13

Thread() VS Thread(String<name>) Thread firstthread = new Thread(); Thread secondthread = new Thread("namedThread"); System.out.println(firstThread.getName()); System.out.println(secondThread.getName()); The output from the above lines would be: Thread-0 namedthread Note that the name of the variable holding the address of a thread is not the same as the name of the thread! More often than not, however, we do not need to know the latter. 14

sleep Method sleep is used to make a thread pause for a specified number of milliseconds. For example: mythread.sleep(1500); //Pause for 1.5 seconds. This suspends execution of the thread and allows other threads to be executed. When the sleeping time expires, the sleeping thread returns to a ready state, waiting for the processor. 15

interrupt Method interrupt may be used to interrupt an individual thread. In particular, this method may be used by other threads to awaken a sleeping thread before that thread s sleeping time has expired. Since method sleep will throw a checked exception (an InterruptedException) if another thread invokes the interrupt method, it must be called from within a try block that catches this exception. 16

Example 1 ThreadShowName.java In this example, static method random from core class Math is used to generate a random sleeping time for each of two threads that simply display their own names ten times. If we were to run the program without using a randomizing element, then it would simply display alternating names, which would be pretty tedious and would give no indication that threads were being used. Method random returns a random decimal value in the range 0-0.999, which is then multiplied by a scaling factor of 3000 and typecast into an int, producing a final integer value in the range 0-2999. Note the use of extends Thread in the opening line of the class. Though this class already implements the Runnable interface (and so has a definition of method run), the default implementation of run does nothing and must be overridden by a definition that we supply. 17

Example 1 ThreadShowName.java 18

Example 1 ThreadShowName.java 19

Example 1 ThreadShowName.java In this program, each of the two threads was carrying out exactly the same task, which meant that each of them could be created from the same Thread class and make use of exactly the samerun method. In practice, of course, different threads will normally carry out different tasks. If we want the threads to carry out actions different from each other's, then we must create a separate class for each thread (each with its own run method), as shown in the next example. 20

Example 2 ThreadHelloCount.java In this example, we shall again create two threads, but we shall have one thread display the message Hello five times and the other thread output integers 0-4. For the first thread, we shall create a class called HelloThread; for the second, we shall create class CountThread. Note that it is NOT the main application class (ThreadHelloCount, here) that extends class Thread this time, but each of the two subordinate classes, HelloThread and CountThread. Each has its own version of the run method. 21

Example 2 ThreadHelloCount.java 22

Example 2 ThreadHelloCount.java 23

Using Threads in Java 1. Extending the Thread Class 2. Explicitly Implementing the Runnable Interface 24

Explicitly Implementing the Runnable Interface This is very similar to the previously described. With this method, however, 1. we first create an application class that explicitly implements the Runnable interface. 2. Then, in order to create a thread, we instantiate an object of our Runnable class and wrap it in a Thread object. We do this by creating a Thread object and passing the Runnable object as an argument to the Thread constructor. (Recall that the Thread class has seven constructors.) There are two Thread constructors that allow us to do this: Thread(Runnable <object>) Thread(Runnable <object>, String <name>) (this constructor allows us also to name the thread.) When either of these constructors is used, the Thread object uses the run method of the Runnable object in place of its own (empty) run method. 25

Explicitly Implementing the Runnable Interface Once a Runnable object has been used as an argument in the Thread constructor, we may never again need to refer to it. If this is the case, we can create such an object anonymously and dynamically by using the operator new in the argument supplied to the Thread constructor, as shown in the following example. However, some people may prefer to create a named Runnable object first and then pass that to the Thread constructor, so the alternative code is also shown. The second method employs about twice as much code as the first, but might serve to make the process clearer. 26

Example 3 RunnableShowName.java (Same effect as that of ThreadShowName) Note that, since the thread objects in this example are not of class Thread (since RunnableShowName does NOT extend Thread), they cannot make direct use of methods getname and sleep, but must go through class Thread to make use of static methods currentthread and sleep. The former method is used to get a pointer to the current thread, in order to use that pointer to call method getname. 27

Example 3 RunnableShowName.java 28

Example 4 RunnableHelloCount.java Modify the program ThreadHelloCount to use the alternative method for multithreading (i.e. implementing the Runnable interface). Name your main class RunnableHelloCount and your subsidiary classes RunnableHello and RunnableCount respectively. The first should display the message 'Hello!' five times (with a random delay of 0-3 seconds between consecutive displays), while the second should display integers 0 to 4. Note that it will NOT be the main class that implements the Runnable interface, but each of the two subsidiary classes. 29

Example 4 RunnableHelloCount.java 30

Example 4 RunnableHelloCount.java 31

Example 4 RunnableHelloCount.java 32

Example 4 RunnableHelloCount.java 33

Multithreaded Servers The multithreaded technique has a couple of significant benefits: it offers a 'clean' implementation, by separating the task of allocating connections from that of processing each connection; it is robust, since a problem with one connection will not affect other connections. The basic technique involves a two-stage process: 1. the main thread (the one running automatically in method main) allocates individual threads to incoming clients; 2. the thread allocated to each individual client then handles all subsequent interaction between that client and the server (via the thread's run method). 34

Multithreaded Servers Since each thread is responsible for handling all further dialogue with its particular client, the main thread can 'forget' about the client once a thread has been allocated to it. It can then concentrate on its simple tasks of waiting for clients to make connection and allocating threads to them as they do so. For each client-handling thread that is created, of course, the main thread must ensure that the client-handling thread is passed a reference to the socket that was opened for the associated client. The separation of responsibilities means that, if a problem occurs with the connection to a particular client, it has no effect on the connections to other clients and there is no general loss of service. This is a major benefit, of course. 35

Example 5 MultiEchoServer.java This is another echo server implementation, but one that uses multithreading to return messages to multiple clients. It makes use of a support class called ClientHandler that extends class Thread. Whenever a new client makes connection, a ClientHandler thread is created to handle all subsequent communication with that particular client. When the ClientHandler thread is created, its constructor is supplied with a reference to the relevant socket. 36

Example 5 MultiEchoServer.java 37

Example 5 MultiEchoServer.java 38

Example 5 MultiEchoClient.java The code required for the client program is exactly that which was employed in the TCPEchoClient program. However, since (i) there was only a modest amount of code in the run method for that program, (ii) we should avoid confusion with the run method of the Thread class and (iii) it'll make a change (!) without being harmful, all the executable code has been placed inside main in the MultiEchoClient program below. 39

Example 5 MultiEchoClient.java 40

Example 5 MultiEchoClient.java 41

Example 5 MultiEchoClient.java 42

Example 5 43

Locks and Deadlock As mentioned previously, writing multithreaded programs can present some awkward problems, primarily caused by the need to coordinate the activities of the various threads that are running within an application. In order to illustrate what can go wrong, consider the following situation, where thread1 and thread2 both need to update a running total called sum. thread1 add 5 23 thread2 add 19 If the operation that each thread is trying to execute were an atomic operation (i.e., one that could not be split up into simpler operations), then there would be no problem. Though this might at first appear to be the case, this is not so. In order to update sum, each thread will need to complete the following series of smaller operations: read the current value of sum, create a copy of it, add the appropriate amount to this copy and then write the new value back. The final value from the two original update operations, of course, should be 47 (=23+5+19). However, if both reads occur before a write takes place, then one update will overwrite the other and the result will be either 28 (=23+5) or 42 (=23+19). The problem is that the sub-operations from the two updates may overlap each other. 44

Locks and Deadlock In order to avoid this problem in Java, we can require a thread to obtain a lock on the object that is to be updated. Only the thread that has obtained the lock may then update the object. Any other (updating) thread must wait until the lock has been released. Once the first thread has finished its updating, it should release the lock, making it available to other such threads. (Note that threads requiring read-only access do not need to obtain a lock.) 45

Locks and Deadlock One unfortunate possibility with this system, however, is that deadlock may occur. A state of deadlock occurs when threads are waiting for events that will never happen. Consider the example where, thread1 has a lock on resource res1, but needs to obtain a lock on res2 in order to complete its processing (so that it can release its lock on res1). At the same time, however, thread2 has a lock on res2, but needs to obtain a lock on res1 in order to complete its processing. Unfortunately, only good design can avoid such situations. Next, we consider how locks are implemented in Java. thread1 has lock needs lock res1 res2 needs lock has lock thread2 46

Synchronizing Threads Locking is achieved by placing the keyword synchronized in front of the method definition or block of code that does the updating. Example public synchronized void updatesum(int amount) { sum+=amount; } If sum is not locked when the above method is invoked, then the lock on sum is obtained, preventing any other thread from executing updatesum. All other threads attempting to invoke this method must wait. Once the method has finished execution, the lock is released and made available to other threads. If an object has more than one synchronized method associated with it, then only one may be active at any given time. 47

Synchronizing Threads In order to improve thread efficiency and to help avoid deadlock, the following methods are used: wait(); notify(); notifyall(). If a thread executing a synchronized method determines that it cannot proceed, then it may put itself into a waiting state by calling method wait. This releases the thread's lock on the shared object and allows other threads to obtain the lock. A call to wait may lead to an InterruptedException, which must either be caught or declared to be thrown by the containing (synchronized) method. 48

Synchronizing Threads When a synchronized method reaches completion, a call may be made to notify, which will 'wake up' a thread that is in the waiting state. Since there is no way of specifying which thread is to be woken, this is only really appropriate if there is only one waiting thread. If all threads waiting for a lock on a given object are to be woken, then we use notifyall. However, there is still no way of determining which thread gets control of the object. The JVM will make this decision. Methods wait, notify and notifyall may only be called when the current thread has a lock on the object (i.e., from within a synchronized method or from within a method that has been called by a synchronized method). If any of these methods is called from elsewhere, an IllegalMonitorStateException is thrown. 49

Example 6 This example is the classical producer-consumer problem, in which a producer is generating instances of some resource and a consumer is removing instances of the resource. The resource will be modelled by a Resource class, while the producer and consumer will be modelled by a Producer class and a ConsumerClient class respectively. The Producer class will be a thread class, extending class Thread. The server program, ResourceServer, will create a Resource object and then a Producer thread, passing the constructor for this thread a reference to the Resource object. The server will then start the thread running and begin accepting connections from ConsumerClients. As each client makes connection, the server will create an instance of ClientThread (another Thread class), which will be responsible for handling all subsequent dialogue with the client. 50

Example 6 Producer.java Method addone of Resource will be called by a Producer object and will attempt to add one item to the resource level. Method takeone of Resource will be called by a ConsumerClient object and will attempt to remove/consume one item. Both of these methods will return the new resource level. Since each of these methods will modify the resource level, they must both be declared with the keyword synchronized. 51

Example 6 Resource.java Just as a factory may not produce more than it can either sell or store, so the producer normally has some maximum resource level beyond which it must not produce. In this simple example, the resource level will not be allowed to exceed 5. Once the resource level has reached 5, production must be suspended. This is done from method addone by calling wait from within a loop that continuously checks whether the resource level is still at maximum. The calling of wait suspends the Producer thread and releases the lock on the shared resource level variable, allowing any ConsumerClient to obtain it. When the resource level is below the maximum, addone increments the level and then calls method notifyall to 'wake up any waiting ConsumerClient thread. 52

Example 6 Resource.java At the other extreme, the consumer must not be allowed to consume when there is nothing to consume (i.e., when the resource level has reached zero). Thus, if the resource level is at zero when method takeone is executed, wait is called from within a loop that continuously checks that the level is still at zero. The calling of wait suspends the ConsumerClient thread and releases the lock on the shared resource level variable, allowing any Producer to obtain it. When the resource level is above zero, takeone decrements the level and then calls method notify to 'wake up' any waiting Producer thread. 53

Example 6 ClientThread.java The ClientThread objects created by ResourceServer handle all resource requests from their respective clients. In this simplified example, clients will be allowed to request only one item at a time from the resource 'pile', which they will do simply by sending a '1'. When a client wishes to disconnect from the service, it will send a '0'. Note that, although ClientThread calls takeone to 'consume' an item of resource on behalf of the client, the only thing that is actually sent to the client is a symbolic message of confirmation that the request has been granted. Only when the material on SERIALIZATION has been covered will it be clear how general resource 'objects' may actually be sent to a client. 54

Example 6 ConsumerClient.java All that remains to be done now is to produce the code for the ConsumerClient class. However, the required code for this class is very similar in structure to that of MultiEchoClient. 55

Example 6 The following screenshots show example output from ResourceServer and two ConsumerClients. 56