Download presentation
Presentation is loading. Please wait.
Published byAugustus Tucker Modified over 8 years ago
1
CS499 – Mobile Application Development Fall 2013 Threads & Android – Part 1
2
Carnegie Mellon Concurrent Programming Multiple processes – each logical control flow is a process. Some form of IPC (InterProcess Communication) needed Multiple threads – multiple logical control flows within a single process. Shared address space I/O multiplexing – event driven concurrency. Shared address space
3
Threads What is a thread? – Conceptual View Parallel computations running in a process – Implementation View Each thread has a program counter and a stack The heap and static areas are shared across threads
4
Computation Abstractions
5
Concurrent Threads
6
Processes vs. Threads
7
Process vs. Threads Process = process context + code, data, and stack shared libraries run-time heap 0 read/write data Program context: Data registers Condition codes Stack pointer (SP) Program counter (PC) Code, data, and stack read-only code/data stack SP PC brk Process context Kernel context: VM structures Descriptor table brk pointer
8
Process with Two Threads shared libraries run-time heap 0 read/write data Program context: Data registers Condition codes Stack pointer (SP) Program counter (PC) Code, data, and kernel context read-only code/data stack SP PC brk Thread 1 Kernel context: VM structures Descriptor table brk pointer Program context: Data registers Condition codes Stack pointer (SP) Program counter (PC) stack SP Thread 2
9
Android Threads Activities have a main thread – the UI thread App components in the same process use the same main thread User interaction, system callback & lifecycle methods are handled in the UI thread It is essential that the UI remains responsive UI toolkit not thread-safe. – A piece of code is thread-safe if it only manipulates shared data structures in a manner that guarantees safe execution by multiple threads at the same time.
10
Java Thread Programming Threads and synchronization supported at the language level Threads managed by the JVM (or DVM in our case)
11
Basic Java Thread Use Case Instantiate a Thread object Invoke the Thread’s start() method – Thread will invoke its own run() Thread terminates when run() returns
12
Simple Example: Using Runnable public class BytePrinter implements Runnable { public void run() { for (int b = -128; b < 128; b++) System.out.println(b); } public class ThreadTest { public static void main(String[] args) { Thread bp1 = new Thread(new BytePrinter()); Thread bp2 = new Thread(new BytePrinter()); Thread bp3 = new Thread(new BytePrinter()); bp1.start(); bp2.start(); bp3.start(); System.out.println(“I am the main thread”); } start threads create thread instances
13
Pros and Cons of Thread-Based Designs + Easy to share data structures between threads – e.g., logging information, file cache + Threads are more efficient than processes – Unintentional sharing can introduce subtle and hard-to-reproduce errors! The ease with which data can be shared is both the greatest strength and the greatest weakness of threads
14
Carnegie Mellon Thread Programming is Hard! Thinking about all possible sequences of events in a computer system is at least error prone and frequently impossible Classical problem classes of concurrent programs: – Races: outcome depends on arbitrary scheduling decisions elsewhere in the system – Deadlock: improper resource allocation prevents forward progress – Livelock / Starvation / Fairness: external events and/or system scheduling decisions can prevent sub-task progress
15
Deadlock In a multi-programmed environment, processes/threads compete for (exclusive) use of a finite set of resources Deadlock occurs when we have a cycle of dependencies. A is waiting on B and B is waiting on A – deadlock!
16
Race Conditions Situations where multiple processes are writing or reading some shared data and the final result depends on who runs precisely when are called race conditions. A serious problem for most concurrent systems using shared variables! Maintaining data consistency requires mechanisms to ensure the orderly execution of cooperating processes. We must make sure that some high-level code sections are executed atomically. Atomic operation means that it completes in its entirety without worrying about interruption by any other potentially conflict-causing process.
17
Concurrent Access to Shared Data Suppose that two threads A and B have access to a shared variable “Balance”. THREAD A: THREAD B: Balance = Balance - 100 Balance = Balance + 200
18
Concurrent Access to Shared Data The statement “ Balance = Balance – 100 ” is implemented by several machine level instructions such as: movl (%ecx),%eax subl %eax,%edx movl %eax, (%ecx) Similarly, “ Balance = Balance + 200 ” can be implemented by the following: movl (%ecx),%eax addl %eax,%ebx movl %eax,(%ecx)
19
Race Conditions Scenario 1: movl (%ecx),%eax subl %eax,%edx movl %eax, (%ecx) Context Switch movl (%ecx),%eax addl %eax,%ebx movl %eax,(%ecx) Balance is increased by 100 Observe: In a time-shared system the exact instruction execution order cannot be predicted Scenario 2: movl (%ecx),%eax subl %eax,%edx Context Switch movl (%ecx),%eax addl %eax,%ebx movl %eax,(%ecx) Context Switch movl %eax, (%ecx) Balance is decreased by 100
20
Ornamental Garden Problem People enter an ornamental garden through either of two turnstiles. Management wish to know how many are in the garden at any time. The concurrent program consists of two concurrent threads and a shared counter object. from Concurrency: State Models & Java Programming, by J. Magee, J Kramer
21
Turnstile class class Turnstile extends Thread { NumberCanvas display; Counter people; Turnstile(NumberCanvas n,Counter c) { display = n; people = c; } public void run() { try{ display.setvalue(0); for (int i=1;i<=Garden.MAX;i++){ Thread.sleep(500); //0.5 second between arrivals display.setvalue(i); people.increment(); } } catch (InterruptedException e) {} } The run() method exits and the thread terminates after Garden.MAX visitors have entered.
22
Counter class class Counter { int value=0; NumberCanvas display; Counter(NumberCanvas n) { display=n; display.setvalue(value); } void increment() { int temp = value; //read value Simulate.HWinterrupt(); value=temp+1; //write value display.setvalue(value); } Hardware interrupts can occur at arbitrary times. The counter simulates a hardware interrupt during an increment(), between reading and writing to the shared counter value. Interrupt randomly calls Thread.sleep() to force a thread switch.
23
ornamental garden program private void go() { counter = new Counter(counterD); west = new Turnstile(westD,counter); east = new Turnstile(eastD,counter); west.start(); east.start(); } The Counter object and Turnstile threads are created by the go() method of the Garden applet:
24
ornamental garden program - display After the East and West turnstile threads have each incremented its counter 20 times, the garden people counter is not the sum of the counts displayed. Counter increments have been lost. Why?
25
concurrent method activation Java method activations are not atomic - thread objects east and west may be executing the code for the increment method at the same time. east west increment: read value write value + 1 program counter program counter PC shared code
26
Solution? Synchronization Synchronization –Most synchronization can be regarded as either: Mutual exclusion (making sure that only one process is executing a CRITICAL SECTION [touching a variable or data structure, for example] at a time), or as CONDITION SYNCHRONIZATION, which means making sure that a given process does not proceed until some condition holds (e.g. that a variable contains a given value) Competition Cooperation
27
critical section Code segment that needs to execution atomically (i.e. only one thread at a time, running to completion). If increment is a critical section, west is forced to wait for east to complete the increment. east west increment: read value write value + 1 program counter program counter PC shared code
28
Mutual Exclusion
29
Mutual exclusion in Java class SynchronizedCounter extends Counter { SynchronizedCounter(NumberCanvas n) {super(n);} synchronized void increment() { super.increment(); } We correct COUNTER class by deriving a class from it and making the increment method synchronized: Concurrent activations of a method in Java can be made mutually exclusive by prefixing the method with the keyword synchronized, which uses a lock on the object. acquire lock release lock
30
mutual exclusion - the ornamental garden Java associates a lock with every object. The Java compiler inserts code to acquire the lock before executing the body of the synchronized method and code to release the lock before the method returns. Concurrent threads are blocked until the lock is released.
31
Java Locks and Synchronization Every object has an intrinsic lock associated with it. A thread that needs exclusive and consistent access to an object's fields has to acquire the object's intrinsic lock before accessing them, and then release the intrinsic lock when it's done with them. A thread is said to own the intrinsic lock between the time it has acquired the lock and released the lock. As long as a thread owns an intrinsic lock, no other thread can acquire the same lock. The other thread will block when it attempts to acquire the lock.
32
Java Locks and Synchronization When a thread invokes a synchronized method, it automatically acquires the intrinsic lock for that method's object and releases it when the method returns (even if it returns via an exception) Statements inside a method can by synchronized as well. This is useful in cases where the methods of other objects are invoked. synchronized(this) { lastName = name; nameCount++; } nameList.add(name); }
33
Java synchronized statement Access to an object may also be made mutually exclusive by using the synchronized statement: synchronized (object) { statements } A less elegant way to correct the example would be to modify the Turnstile.run() method: synchronized(people) {people.increment();} Why is this “less elegant”? Relying on the user to act responsibly. To ensure mutually exclusive access to an object, all object methods should be synchronized.
34
Creating Lock Objects public class DualCounters { private long c1 = 0; private long c2 = 0; private Object lock1 = new Object(); private Object lock2 = new Object(); public void inc1() { synchronized(lock1) { c1++; } } public void inc2() { synchronized(lock2) { c2++; } } Must be done with care!
35
Java Collections java.util.concurrent package includes a number of additions to the Java Collections Framework. BlockingQueue defines a first-in-first-out data structure that blocks or times out when you attempt to add to a full queue, or retrieve from an empty queue. BlockingQueue ConcurrentMap is a subinterface of java.util.Map that defines useful atomic operations. These operations remove or replace a key-value pair only if the key is present, or add a key-value pair only if the key is absent. Making these operations atomic helps avoid synchronization. The standard general-purpose implementation of ConcurrentMap is ConcurrentHashMap, which is a concurrent analog of HashMap. ConcurrentMapjava.util.MapConcurrentHashMapHashMap
36
Atomic Variables class SynchronizedCounter { private int c = 0; public synchronized void increment() { c++; } public synchronized void decrement() { c--; } public synchronized int value() { return c; } } import java.util.concurrent.atomic.AtomicInteger; class AtomicCounter { private AtomicInteger c = new AtomicInteger(0); public void increment() { c.incrementAndGet(); } public void decrement() { c.decrementAndGet(); } public int value() { return c.get(); } }
37
Condition Synchronization public class checkpoint { boolean here_first = true; synchronized void meet_up () { if (here_first) { here_first = false; wait(); } else { notify(); here_first = true; } };
38
Condition Synchronization wait(), notify(), notifyall() We can call the wait() method of any Java object, which suspends the current thread. The thread is said to be "waiting on" the given object. Another thread calls the notify() method of the same Java object. This "wakes up" one of the threads waiting on that object. notifyall() methods “wakes up” all of the threads waiting on that object.
39
Producer/Consumer Problem ProducerConsumer bounded size buffer (N) Producer and Consumer execute concurrently but only one should be accessing the buffer at a time. Producer puts items to the buffer area but should not be allowed to put items into a full buffer Consumer process consumes items from the buffer but cannot remove information from an empty buffer Competition Cooperation
40
Bounded Buffer public class BufferImpl implements Buffer { protected E[] buf; protected int in = 0; protected int out= 0; protected int count= 0; protected int size; public BufferImpl(int size) { this.size = size; buf = (E[])new Object[size];} public synchronized void put(E o) throws InterruptedException { while (count==size) wait(); buf[in] = o; ++count; in=(in+1) % size; notifyAll(); } public synchronized E get() throws InterruptedException { while (count==0) wait(); E o = buf[out]; buf[out]=null; --count; out=(out+1) % size; notifyAll(); return (o); }
41
Bounded Buffer class Producer implements Runnable { Buffer buf; String alphabet= "abcdefghijklmnopqrstuvwxyz"; Producer(Buffer b) {buf = b;} public void run() { try { int ai = 0; while(true) { ThreadPanel.rotate(12); buf.put(alphabet.charAt(ai)); ai=(ai+1)%alphabet.length(); ThreadPanel.rotate(348); } }catch (InterruptedException e){} } class Consumer implements Runnable { Buffer buf; Consumer(Buffer b) {buf = b;} public void run() { try { while(true) { ThreadPanel.rotate(180); Character c = buf.get(); ThreadPanel.rotate(180); } }catch(InterruptedException e){} }
42
Bounded Buffer public class BoundedBuffer extends Applet { ThreadPanel prod; ThreadPanel cons; public void init() { super.init(); // Set up Display prod = new ThreadPanel("Producer",Color.blue); cons = new ThreadPanel("Consumer",Color.yellow); … } public void start() { Buffer b = new DisplayBuffer(buffDisplay,5); // Create Thread prod.start(new Producer(b)); cons.start(new Consumer(b)); } public void stop() { prod.stop(); cons.stop(); }
43
Semaphore Object public class Semaphore { private int value ; Semaphore(int n) { value = n;} public synchronized void v() { value = value + 1; notifyAll(); } public synchronized void p() throws InterruptedException { while (value == 0) wait(); value = value - 1; } Semaphores were invented by Edsger Dijkstra. p() & v() came from the Dutch words for wait & signal. Useful for mutual exclusion.
44
Reader/Writer – Version 1 public class ReaderWriter { public static void main(String[] args) { Semaphore mutual_exclusion = new Semaphore(1); Reader r1 = new Reader(1,mutual_exclusion); Reader r2 = new Reader(2,mutual_exclusion); Writer w1 = new Writer(1,mutual_exclusion); r1.start(); r2.start(); w1.start(); } Multiple readers & writers to a shared object. Must ensure: 1 – writers can’t overlap 2 – readers & writers can’t overlap 3 – allow multiple readers
45
RW – Version 1 public class Reader extends Thread { int id; Semaphore mutex; Reader(int c,Semaphore s) {id = c; mutex = s;} public void run() { int i = 0; while (i < 10) { try { mutex.p(); } catch (InterruptedException e) {} System.out.println(id + " start Reading"); try { Thread.sleep(500); } catch (InterruptedException e) {} System.out.println(id + " stop Reading"); mutex.v(); try {Thread.sleep(500); } catch (InterruptedException e) {} i = i + 1; } Writer.java is similar…
46
Version 1 notes Mutual exclusion achieved. However, this means only one reader at a time… Continuing on the semaphore approach, can create a counter (for number of readers) and second semaphore… Writer unchanged
47
RW – Version 2 public class ReaderWriter { public static void main(String[] args) { Semaphore mutual_exclusion = new Semaphore(1); Semaphore reader_mutex = new Semaphore(1); Counter num_readers = new Counter(0); Reader r1 = new Reader(1,mutual_exclusion, reader_mutex,num_readers); Reader r2 = new Reader(2,mutual_exclusion, reader_mutex,num_readers); Writer w1 = new Writer(1,mutual_exclusion); r1.start(); r2.start(); w1.start(); }
48
RW – Version 2 public class Reader extends Thread { int id;Semaphore mutex; Semaphore read_mutex;Counter readers; Reader(int c,Semaphore s,Semaphore r,Counter num_r) { id = c; mutex = s; read_mutex=r; readers = num_r;} public void run() { int i = 0; while (i < 10) { read_mutex.p(); readers.incr(); if (readers.get() == 1) mutex.p(); read_mutex.v(); System.out.println(id + " start Reading"); Thread.sleep(500); System.out.println(id + " stop Reading"); read_mutex.p(); readers.decr(); if (readers.get() == 0) mutex.v(); read_mutex.v(); Thread.sleep(500); i = i + 1; } }} Writer.java as in Version 1
49
Reader/Writer Monitor Soln class ReadWriteSafe implements ReadWrite { private int readers =0; private boolean writing = false; public synchronized void acquireRead() throws InterruptedException { while (writing) wait(); ++readers; } public synchronized void releaseRead() { --readers; if(readers==0) notifyAll(); } Multiple readers & writers to a shared object. Must ensure: 1 – writers can’t overlap 2 – readers & writers can’t overlap 3 – allow multiple readers
50
public synchronized void acquireWrite() throws InterruptedException { while (readers>0 || writing) wait(); writing = true; } public synchronized void releaseWrite() { writing = false; notifyAll(); } Reader/Writer Monitor Soln
51
class ReadWritePriority implements ReadWrite{ private int readers =0; private boolean writing = false; private int waitingW = 0; // no of waiting Writers. public synchronized void acquireRead() throws InterruptedException { while (writing || waitingW>0) wait(); ++readers; } public synchronized void releaseRead() { --readers; if (readers==0) notifyAll(); } RW WritePriority Monitor Soln
52
public synchronized void acquireWrite() throws InterruptedException { ++waitingW; while (readers>0 || writing) wait(); --waitingW; writing = true; } public synchronized void releaseWrite() { writing = false; notifyAll(); } RW WritePriority Monitor Soln
53
class ReadWriteFair implements ReadWrite { private int readers =0; private boolean writing = false; private int waitingW = 0; // no of waiting Writers. private boolean readersturn = false; synchronized public void acquireRead() throws InterruptedException { while (writing || (waitingW>0 && !readersturn)) wait(); ++readers; } synchronized public void releaseRead() { --readers; readersturn=false; if(readers==0) notifyAll(); } RW Fair Monitor Soln
54
synchronized public void acquireWrite() throws InterruptedException { ++waitingW; while (readers>0 || writing) wait(); --waitingW; writing = true; } synchronized public void releaseWrite() { writing = false; readersturn=true; notifyAll(); } RW Fair Monitor Soln
55
Thread Joining A thread can wait for the completion of a thread by using the join() method class Worker2 implements Runnable { public void run() { System.out.println(“Worker thread.”); } public class Second { public static void main(String args[]) { Thread thrd = new Thread(new Worker2()); thrd.start(); System.out.println(“Main thread.”); try { thrd.join(); } catch (InterrruptedException) ie) { } }
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.