Schedule • Last week Tomcat & Concurrency – Java Servlets and JSP Control • Today – Tomcat – Concurrency control – Midterm results • Average: 55.5% Nan Niu ([email protected]) • Model answer and mark-distribution are available CSC309 -- Fall 2008 • This Thursday – A1 re-marking – A2 office hour 2

What is Tomcat? Getting Started • A servlet container -- a Web server that • The “student guide” has detailed can host Java servlets and JSPs in instructions for setting up Tomcat on CDF addition to more traditional Web content • See the course website to find your • We’ll be using version 5.5.26 assigned port number

• Always to remember to stop your server before logging out

3 4

Deploying Applications web.xml • An application, e.g., the sample csc309 • Web Application Deployment Descriptor application, is deployed by placing it in file Tomcat’s webapps directory • Tells the server which URL corresponds to which servlet: • Note the required directory structure: SampleServletName HelloWorld

SampleServletName /servlet/HelloWorld/

5 6

1 Accessing a Servlet Tomcat Directories • Visit • bin: Includes startup and shutdown scripts http://machineName:portNum/pathToServlet, where machineName is the machine on which the • conf: Configuration files including server.xml (on CDF, server is running, and portNum is your assigned this is generated the first time you run bin/start.sh) and port number tomcat-users.xml – e.g., http://redwolf.cdf.toronto.edu:9999/csc309/servlet/ • logs: Server’s log files HelloWorld – e.g., • webapps: Applications http://localhost:9999/csc309/serlvet/HelloWorld • Never hardcode machine names or port numbers • work: Server’s temporary files. It is safe (and sometimes in your applications -- use relative URLs instead! helpful) to delete this directory after the server has been shutdown

7 8

Other Issues about Tomcat Brief Preview of • Tomcat manager • Multiple threads ready to run • Debugging servlets • Some mechanism for switching between • Using Eclipse them • Installing Tomcat on your own computer – Context switches • Some policy for choosing the next to run • Reference: Ali’s tutorial from the summer – This policy may be pre-emptive 2008 term – Meaning thread can’t anticipate when it may be forced to yield the CPU – By design, it is not easy to detect it has happened (only the timing changes)

9 10

Synchronization Motivating Example • Threads interact in a multiprogrammed • Suppose we write functions to handle system withdrawals and deposits to bank account: – To share resources (such as shared data) Withdraw(acct, amt) { Deposit(acct, amt) { balance = get_balance(acct); balance = get_balance(acct); – To coordinate their execution balance = balance - amt; balance = balance + amt; put_balance(acct,balance); put_balance(acct,balance); • Arbitrary interleaving of thread executions return balance; return balance; can have unexpected consequences } } – We need a way to restrict the possible • Now suppose you share this account with interleavings of executions someone and the balance is $1000 – Scheduling is invisible to the application • You each go to separate ATM machines - you • Synchronization is the mechanism that gives withdraw $100 and your S.O. deposits $100 us this control 11 12

2 Motivating Example (Cont’d) Interleaved Schedules • We can represent this situation by creating • The problem is that the execution of the two separate threads for each action, which may run processes can be interleaved: at the bank’s central server (or at the ATM): Schedule A Schedule B balance = get_balance(acct); balance = get_balance(acct); Withdraw(acct, amt) { Deposit(account, amount) { balance = balance - amt; balance = balance - amt; balance = get_balance(acct); balance = get_balance(acct); balance = balance - amt; balance = balance + amt; balance = get_balance(acct); Context balance = get_balance(acct); put_balance(acct,balance); put_balance(acct,balance); balance = balance + amt; switch balance = balance + amt; return balance; return balance; put_balance(acct, balance); } } put_balance(acct, balance); put_balance(acct, balance); put_balance(acct, balance); • What’s wrong with this implementation? • What is the account balance now? • Think about potential schedules for these two • Is the bank happy with our implementation? threads • Are you?

13 14

What Went Wrong? What Program Data is Shared? • Two concurrent threads manipulated a • Local variables are not shared (private) shared resource (the account) without – Each thread has its own stack any synchronization – Local vars are allocated on this private stack – Outcome depends on the order in which – Never pass/share/store a pointer to a local variable accesses take place on another thread’s stack! • This is called a race condition • Global variables and static objects are shared • We need to ensure that only one thread – Stored in the static data segment, accessible by any at a time can manipulate the shared thread resource • Dynamic objects and other heap objs are – So that we can reason about program shared behavior – Allocated from heap with new/delete  We need synchronization – Any properties/attributes of a class 15 16

Mutual Exclusion The Critical Section Problem • Given: • Design a protocol that threads can use to cooperate – Each thread must request permission to enter its CS, in its – A set of n threads, T1, T2, …, Tn entry section – A set of resources shared between threads – CS may be followed by an exit section – A segment of code which accesses the shared – Remaining code is the remainder section resources, called the critical section, CS remainder • We want to ensure that: Entry – Only one thread at a time can execute in the CS CS – All other threads are forced to wait on entry Exit remainder – When a thread leaves the CS, another can enter • Each thread is executing at non-zero speed – no assumptions about relative speed

17 18

3 Critical Section Requirements High-level Abstractions for CS’s  Mutual Exclusion • Locks – If one thread is in the CS, then no other is – Very primitive, minimal semantics  Progress – If no thread is in the CS, and some threads want to • Semaphores enter CS, only threads not in the “remainder” – Basic, easy to understand, hard to program with section can influence the choice of which thread • Monitors enters next, and choice cannot be postponed indefinitely – High-level, ideally has language support (Java)  Bounded waiting (no starvation) • Messages – If some thread T is waiting on the CS, then there is – Simple model for communication & synchronization a limit on the number of times other threads can – Direct application to distributed systems enter CS before this thread is granted access • Performance – The overhead of entering and exiting the CS is small with respect to the work being done within it 19 20

Using Locks Monitors Function Definitions

Withdraw(acct, amt) { • an abstract data type (data and Possible schedule acquire(); operations on the data) with the balance = get_balance(acct); acquire(lock); balance = balance - amt; balance = get_balance(acct); restriction that only one process at a put_balance(acct,balance); balance = balance - amt; release(lock); time can be active within the monitor return balance; acquire(lock); } – Local data accessed only by the monitor’s Deposit(account, amount) { put_balance(acct, balance); release(lock); procedures (not by any external procedure) acquire(lock); balance = get_balance(acct); balance = get_balance(acct); – A process enters the monitor by invoking 1 balance = balance + amt; balance = balance + amt; of its procs put_balance(acct,balance); put_balance(acct, balance); release(lock); release(lock); – Other processes that attempt to enter return balance; } monitor are blocked

21 22

More on Monitors Java Synchronization • If no process is suspended, a signal has no effect • Use synchronized Java keyword to restrict execution to 1 thread • Method level • If process P executes an x.signal operation and $ a class public Example { suspended process Q associated with condition x, then synchronized public void doSomething() { // Only one thread can execute we have a problem: } // method at any time – P is already “in the monitor”, does not need to block } – Q becomes unblocked by the signal, and wants to resume • Object execution in the monitor class public Example { – but both cannot be simultaneously active in the monitor! public void doSomething() { synchronized(SomeObject) { // Limit access to only } // one thread per object • Class class public Example { public void doSomething() { synchronized(SomeObject.class) { // Limit access to only } // one thread per class

23 24

4 Synchronization Example Synchronization Example (Cont’d)

• Problem: ensure consistency of a shared public class Singleton { variable in a multithreaded program private volatile static Singleton myUniqueInstance; • Idea: use the singleton pattern to ensure a private Singleton() { } single instance public static Singleton getInstance() { • Problem: possible simultaneous synchronized (Singleton.class) { initializations if (myUniqueInstance == null) { • Idea: use synchronization myUniqueInstance = new Singleton(); } } return myUniqueInstance; } }

25 26

Synchronization Efficiency Synchronization Efficiency Example • Problem: synchronization is expensive public class Singleton { private volatile static Singleton myUniqueInstance; • Solution: check condition first unsynchronized; then, synchronized private Singleton() { } public static Singleton getInstance() { if (myUniqueInstance == null) { synchronized (Singleton.class) { if (myUniqueInstance == null) { myUniqueInstance = new Singleton(); } } } return myUniqueInstance; } } 27 28

Producer-Consumer Problem Producer-Consumer • A group of processes/threads produce data (producers) • A different group of processes/threads Consumer Producer consume data (consumers) monitor { monitor { • Data to be consumed is held in a shared while(buffer.size < 1) add element to buffer wait signal buffer remove first buffer element } – Infinite size for now }

29 30

5 Producer-Consumer ver2 Enforcing Single Class Buffer size = 5 • A process in the monitor may need to wait for something to happen Consumer Producer • May need to allow another process to monitor { monitor { while(buffer.size < 1) while (buffer.size > 4) use the monitor wait wait add element to buffer • Provide a condition type for variables remove first buffer element if (buffer == 1) if (buffer == 4) with operations signal signal • wait (suspend the invoking process) } } • signal (resume exactly one suspended process)

31 32

More Semantics for Signal Hoare vs. Mesa Semantics • Hoare monitors (original) • Hoare • signal() immediately switches from the caller to a waiting thread if (empty) • The condition that the waiter was blocked on is wait(condition); guaranteed to hold when the waiter resumes • Mesa • Need another queue for the signaler, if signaler was not done using the monitor while(empty) • Mesa monitors (Mesa, Java, Nachos, OS/161) wait(condition) • Signal() places a waiter on the ready queue, but • Tradeoffs signaler continues inside monitor – Hoare monitors make it easier to reason about • Condition is not necessarily true when waiter program resumes – Mesa monitors are easier to implement, more • Must check condition again efficient, can support additional ops like broadcast 33 34

Synchronization for Servlets • Problem: multiple service method threads – Solution: synchronization • Do NOT synchronize doGet – Excessive blocking – Does not mutex other servlets • Synchronize on: – Servlet (“instance”) variables – Session -> session synchronized(request.getsession()) – Context -> application scope synchronized(getservletcontext()) • Best idea: do not share resources unnecessarily

35

6