CMSC 433 Programming Language Technologies and Paradigms. Composing Objects

Similar documents
Lecture 10 State dependency

CMSC 433 Programming Language Technologies and Paradigms. Spring 2013

Get out, you will, of this bind If, your objects, you have confined

CSE Lecture 19: Concurrency 11 Nov Nate Nystrom UTA

The Dining Philosophers Problem CMSC 330: Organization of Programming Languages

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

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

Java Threads. COMP 585 Noteset #2 1

CMSC 330: Organization of Programming Languages

5. Liveness and Guarded Methods

CS11 Java. Fall Lecture 7

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

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

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

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

Advanced Concepts of Programming

Concurrency in Java Prof. Stephen A. Edwards

Monitors; Software Transactional Memory

CMSC 330: Organization of Programming Languages

Overview. CMSC 330: Organization of Programming Languages. Concurrency. Multiprocessors. Processes vs. Threads. Computation Abstractions

Concurrent Programming using Threads

Lecture 19: Composing Objects in Java

Chapter 32 Multithreading and Parallel Programming

Recap. Contents. Reenterancy of synchronized. Explicit Locks: ReentrantLock. Reenterancy of synchronise (ctd) Advanced Thread programming.

Monitors; Software Transactional Memory

Models of concurrency & synchronization algorithms

CS 159: Parallel Processing

Threads and Java Memory Model

Composing Objects. Java and Android Concurrency.

Synchronization. Announcements. Concurrent Programs. Race Conditions. Race Conditions 11/9/17. Purpose of this lecture. A8 released today, Due: 11/21

Computation Abstractions. CMSC 330: Organization of Programming Languages. So, What Is a Thread? Processes vs. Threads. A computer.

Design of Thread-Safe Classes

Lecture 29: Java s synchronized statement

Introduction to Locks. Intrinsic Locks

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

Summary Semaphores. Passing the Baton any await statement. Synchronisation code not linked to the data

Synchronization SPL/2010 SPL/20 1

Synchronization in Java

Synchronising Threads

Concurrent Programming Lecture 10

Concurrent and Real-Time Programming in Java

Threads and Parallelism in Java

Lecture 9: Introduction to Monitors

Introduction to OS Synchronization MOS 2.3

Atomic Variables & Nonblocking Synchronization

G52CON: Concepts of Concurrency

Synchronization Lecture 23 Fall 2017

Programming Language Concepts: Lecture 11

Week 7. Concurrent Programming: Thread Synchronization. CS 180 Sunil Prabhakar Department of Computer Science Purdue University

What is a Thread? Why Multicore? What is a Thread? But a fast computer runs hot THREADS AND CONCURRENCY. Concurrency (aka Multitasking)

Principles of Software Construction: Concurrency, Part 2

wait with priority An enhanced version of the wait operation accepts an optional priority argument:

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

CMSC 132: Object-Oriented Programming II

AP COMPUTER SCIENCE JAVA CONCEPTS IV: RESERVED WORDS

Multiple Inheritance. Computer object can be viewed as

Threads Chate Patanothai

COMP31212: Concurrency A Review of Java Concurrency. Giles Reger

COMPSCI 230 Threading Week8. Figure 1 Thread status diagram [

Real-Time and Concurrent Programming Lecture 4 (F4): Monitors: synchronized, wait and notify

Basics of. Multithreading in Java

SYNCHRONIZATION M O D E R N O P E R A T I N G S Y S T E M S R E A D 2. 3 E X C E P T A N D S P R I N G 2018

Part IV Other Systems: I Java Threads

Threads Questions Important Questions

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

CS 333 Introduction to Operating Systems. Class 4 Concurrent Programming and Synchronization Primitives

Dealing with Issues for Interprocess Communication

Synchronization in Concurrent Programming. Amit Gupta

What's wrong with Semaphores?

Synchronization Lecture 24 Fall 2018

Introduction to Java Threads

1 Process Coordination

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

Operating Systems. Lecture 4 - Concurrency and Synchronization. Master of Computer Science PUF - Hồ Chí Minh 2016/2017

Synchronization I. Jo, Heeseung

Concurrency COMS W4115. Prof. Stephen A. Edwards Spring 2002 Columbia University Department of Computer Science

Implementing Coroutines. Faking Coroutines in Java

G52CON: Concepts of Concurrency

Multi-threaded programming in Java

More Shared Memory Programming

RACE CONDITIONS AND SYNCHRONIZATION

CSE332: Data Abstractions Lecture 19: Mutual Exclusion and Locking

Monitors & Condition Synchronization

Performance Throughput Utilization of system resources

CSCI 5828: Foundations of Software Engineering

MVP1: Introduction to concurrency in JAVA

CS 351 Design of Large Programs Threads and Concurrency

Module 6: Process Synchronization. Operating System Concepts with Java 8 th Edition

Monitors & Condition Synchronization

CS180 Review. Recitation Week 15

Dr.-Ing. Michael Eichberg

Concurrent Objects and Linearizability

CS 162 Operating Systems and Systems Programming Professor: Anthony D. Joseph Spring 2004

Midterm on next week Tuesday May 4. CS 361 Concurrent programming Drexel University Fall 2004 Lecture 9

Deadlock Bug Detection Techniques

Component-Based Software Engineering

CS 455: INTRODUCTION TO DISTRIBUTED SYSTEMS [THREADS] Frequently asked questions from the previous class survey

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

Monitors & Condition Synchronisation

CS 31: Introduction to Computer Systems : Threads & Synchronization April 16-18, 2019

Transcription:

CMSC 433 Programming Language Technologies and Paradigms Composing Objects

Composing Objects To build systems we often need to Create thread safe objects Compose them in ways that meet requirements while maintaining safety

Designing Thread-Safe Classes For each class you should know: Which variables make up the object's state What invariants/postconditions apply to the state What policies you will use to manage concurrent access to the object's state

Object State Primitive fields References and the fields reachable from those references

Object Invariants Invariants are logical statements that must be true about an object s state, e.g., lowerbound upperbound List l is sorted in ascending order Postconditions capture the expected effect of an operation, e.g., For list l, after l.add(x) completes l.contains(x)

Synchronization Policy Invariants/postconditions must hold under concurrent access If operations can violate invariants/postconditions Operation must be atomic If invariants involve multiple variables Must fetch and update all variables in an atomic operation All accesses to any of these variables must be guarded by the same lock

Counter public final class Counter { // shared mutable state private long value = 0; // returns current value public synchronized long getvalue() { return value; // increments current value by 1 public synchronized long increment() { if (value == Long.MAX_VALUE) throw new IllegalStateException("counter overflow"); return ++value;

BuggyNumberRange public class BuggyNumberRange { // INVARIANT: lower <= upper private volatile int lower = 0; private volatile int upper = 0; public void setlower(int i) { if (i > upper) throw new IllegalArgumentException(); lower = i; public void setupper(int i) { if (i < lower) throw new IllegalArgumentException(); upper = i; public boolean isinrange(int i) { return (i >= lower && i <= upper);

SimpleNumberRange public class SimpleNumberRange { private int lower = 0; private int upper = 0; public synchronized void setlower(int i) { if (i > upper) throw new IllegalArgumentException(); lower=i; public synchronized void setupper(int i) { if (i < lower) throw new IllegalArgumentException(); upper=i; public synchronized boolean isinrange(int i) { return (i >= lower && i <= upper);

State Dependent Actions State dependent operations are those that are legal in some states, but not in others Examples Operations on collections Cant remove an element from an empty queue Can t add an element to a full buffer Operations involving constrained values Can t withdraw money from empty bank account Operations requiring resources Can t print to a busy printer Operations requiring particular message orderings Can t read an unopened file

State Dependent Actions Some policies for handling state dependence Balking Guarded Suspension Optimistic Retries

Policies for State Dependent Actions There are different ways to handle state dependence Balking Ignore or throw exception Guarding Suspend until you can proceed Trying proceed, but rollback if necessary Retrying keep trying until you succeed Timing out try for a fixed period of time

Balking Check state upon method entry Must not change state in course of checking it Exit immediately if not in right state Throw exception or return special error value Client is responsible for handling failure

Example: Balking Bounded Buffer public class BalkingBoundedBuffer implements Buffer { private List data; private final int capacity; public BalkingBoundedBuffer(int capacity) { data = new ArrayList(capacity); this.capacity = capacity;

Example: Balking Bounded Buffer public synchronized Object take() throws Failure { if (data.size() == 0) throw new Failure("Buffer empty"); Object temp = data.get(0); data.remove(0); return temp; public synchronized void put(object obj) throws Failure { if (data.size() == capacity) throw new Failure("Buffer full"); data.add(obj);

Guarding Check state upon entry If not in acceptable state, wait Some some other thread must cause a state change that enables waiting thread to resume operation Generalization of locking Locked: wait until not engaged in other methods Guarded: wait until arbitrary predicate holds Introduces liveness concerns Relies on actions of other threads to make progress

Guarding Mechanisms Busy-waits Thread continually spins until a condition holds while (!condition) ; // spin // use condition Usually to be avoided, but can be useful when conditions latch i.e., once set true, they never become false Suspension Thread stops execution until notified that the condition may be true Supported in Java via wait-sets and locks

Guarding Via Suspension Waiting for a condition to hold: synchronized (obj) { while (!condition) { try { obj.wait(); catch (InterruptedException ex) {... // make use of condition Always test a condition in a loop State change may not be what you need Conditions can change more than once before waiting thread resumes operation

Guarding Via Suspension Changing a condition: synchronized (obj) { condition = true; obj.notifyall(); // or obj.notify()

Wait-sets and Notification Every Java Object has a wait-set Can only manipulate it while holding Object s lock Otherwise IllegalMonitorStateException is thrown Threads enter Object s wait-set by invoking wait() wait() atomically releases lock and suspends thread Including a lock held multiple times No other held locks are released Optional timed-wait: wait( long millis ) No direct indication that a time-out occurred wait() is equivalent to wait(0) means wait forever

Wait-sets and Notification Threads are released from an Object s wait-set when: notifyall() is invoked on the Object All threads released notify() is invoked on the Object One thread selected at random for release A specified time-out elapses The Thread has its interrupt() method invoked InterruptedException thrown A spurious wakeup occurs Lock is always reacquired before wait() returns Can t be acquired until a notifying Thread releases it Released thread contends with all other threads for the lock If Lock is acquired, then Lock count is restored

Wait-sets and Notifications notify() can only be used safely when Only one thread can benefit from the change of state All threads are waiting for the same change of state Or else another notify() is done by the released thread These conditions hold in all subclasses Any Java Object can be used just for its waitset and/or lock

Guarded Bounded Buffer public synchronized Object take() throws Failure { while (data.size() == 0) try { wait(); catch(interruptedexception ex) { throw new Failure(); Object temp = data.get(0); data.remove(0); notifyall(); return temp

Guarded Bounded Buffer public synchronized void put(object obj) throws Failure { while (data.size() == capacity) try { wait(); catch(interruptedexception ex) { throw new Failure(); data.add(obj); notifyall();

notify vs. notifyall() Suppose put() and take() used notify() instead of notifyall() Capacity is 1 Four threads two just call put() and two just call take()

Deadlock T1 T2 T3 T4 data.size Wait Set take 0 T1 take 0 T1,T2 put 1 T2 put 1 T2,T3 put 1 T2,T3,T4 take 0 T3,T4 take 0 T1, T3,T4 take 0 T1, T2,T3,T4

Timing Out Intermediate points between balking and guarding Can vary timeout parameter from zero to infinity Can t be used for high-precision timing or deadlines Time can elapse between wait and thread resumption Time can elapse after checking the time Java implementation constraints wait(ms) does not automatically tell you if it returned because of a notification or because of a timeout Must check for both. Order and style of checking can matter, depending on If always OK to proceed when condition holds If timeouts signify errors No way to establish with 100% certainty that timeout occurred

Timeout Example // assume timeout > 0 public synchronized void put(object obj, long timeout) throws Failure { long timeleft = timeout; long start = System.currentTimeMillis(); while (data.size() == capacity) { try { wait(timeleft); catch(interruptedexception ex) { throw new Failure(); if (data.size() < capacity) // notified, timed-out or spurious? break; // condition holds - don't care if we timed out else { // maybe a timeout long elapsed = System.currentTimeMillis() - start; timeleft = timeleft- elapsed; if (timeleft <= 0) throw new Failure("Timed-out"); // spurious so wait again data.add(obj); notifyall();

Optimistic Policies: Trying Isolate state into versions e.g. by grouping into a helper class Isolate state changes to atomic commit method that swaps in new state On method entry Record initial state Apply action to new state Only commit if Action succeeds and initial state was unchanged If can t commit: fail or retry Failures are clean (no side effects) Retry policy is variation of a busy-wait Only applicable if actions fully reversible No I/O or thread construction unless safely cancellable All internally called methods must be undoable

Optimistic Techniques May be more efficient than guarded waits when: Conflicts are rare and when running on multiple CPUs However, retrying can cause livelock Infinite retries with no progress Should arrange to fail after a certain time or number of attempts

Optimistic Bounded Counter public class OptimisticBoundedCounter { public synchronized Long count() { return count; private synchronized boolean commit(long oldc, Long newc) { boolean success = (count == oldc); if (success) count = newc; return success; public void inc() { for (;;) { // retry-based Long c = count(); // record current state long v = c.longvalue(); if (v < MAX && commit(c, new Long(v+1)) break; Thread.yield(); // a good idea in spin loops

Instance Confinement Even if an object is not thread-safe, there may still be ways to use it safely, e.g., Confine its use to a single thread Ensure all accesses to it are guarded by a lock

Instance Confinement public class PersonSet { private final Set<Person> myset = new HashSet<Person>(); // HashSet is not thread-safe public synchronized void addperson(person p) { myset.add(p); public synchronized boolean containsperson(person p) { return myset.contains(p);

Monitor Pattern The PersonSet class uses the Monitor Pattern Object enforces mutually exclusive access to its own state Have to be careful when we combine monitors

Containment of Unsafe Objects public static class Statistics { public long requests; public double avgtime; public Statistics(long requests, double avgtime) { this.requests = requests; this.avgtime = avgtime; Fields are public and mutable, so instances can t be shared

Containment of Unsafe Objects class Container{ private final Statistics stats = new Statistics(0,0.0); public synchronized Statistics getstatistics() { return new Statistics(stats.requests, stats.avgtime); private void somefunc() { synchronized(this) { double total = stats.avgtime*stats.requests + elapsed; stats.avgtime = total / (++stats.requests); Can use it in another class Don t want to expose mutable state so we make copies of it

Containment Strict containment creates islands of objects Applies recursively Allows inner code to run faster Can be used with legacy sequential code Requires inner code to be communication closed No unprotected calls into or out of island Requires outer objects to never leak inner references

Containment and Monitor Methods class Part { protected boolean cond = false; synchronized void await() { while (!cond) try { wait(); catch(interruptedexception ex) {... synchronized void signal( boolean c) { cond = c; notifyall(); class Whole{ final Part part = new Part(); synchronized void rely() { part.await(); synchronized void set( boolean c){ part.signal(c); What happens if Whole.rely() is called while cond is false?

Nested Monitors When thread T calls Whole.rely T waits in part While suspended T still holds lock on Whole No other thread will ever unblock T via Whole.set Nested Monitor Lockout

Avoiding Nested Monitors Possible fix Let owner object provide lock and wait-set class Whole { //... class Part { //... public void await() { synchronized (Whole.this) { while (...) Whole.this.wait(); //...

Hierarchical Containment Locking Parts are not hidden from clients Parts use lock provided by common owner Can use either internal or external conventions

Internal Containment Locking Parts use their owners as locks class Part { protected Container owner_; // Never null public Container owner() {return owner_; private void bareaction() { /*... unsafe... */ public void m() { synchronized (owner()){ bareaction(); Parts don t deadlock when invoking each other s methods Parts must be aware that they are contained

External Containment Locking Can require callers to provide the lock class Client { void f(part p) { synchronized (p.owner()) { p.bareaction();

Subclassing Unsafe Code If a class is not thread-safe, can create a subclass that adds synchronization class SafeClass extends UnSafeClass{ synchronized void foo() { super.foo(); and instantiate it instead Can also use unrelated wrapper classes and delegation