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

Similar documents
CS18000: Programming I

The Dining Philosophers Problem CMSC 330: Organization of Programming Languages

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

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

COMPSCI 230 Threading Week8. Figure 1 Thread status diagram [

Synchronization in Concurrent Programming. Amit Gupta

Introduction to Java Threads

Chapter 6: Process Synchronization

Synchronization. CS 475, Spring 2018 Concurrent & Distributed Systems

CS 351 Design of Large Programs Threads and Concurrency

Operating Systems. Designed and Presented by Dr. Ayman Elshenawy Elsefy

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

Chapter 6: Synchronization. Operating System Concepts 8 th Edition,

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

Problems with Concurrency. February 19, 2014

Dealing with Issues for Interprocess Communication

CS 159: Parallel Processing

Threads and Parallelism in Java

CS180 Review. Recitation Week 15

Lesson 6: Process Synchronization

Concurrent Programming: Threads. CS 180 Sunil Prabhakar Department of Computer Science Purdue University

Interprocess Communication By: Kaushik Vaghani

Synchronized Methods of Old Versions of Java

Synchronization Principles

Chapter 6: Synchronization. Chapter 6: Synchronization. 6.1 Background. Part Three - Process Coordination. Consumer. Producer. 6.

More Synchronization; Concurrency in Java. CS 475, Spring 2018 Concurrent & Distributed Systems

Chapter 6: Process Synchronization

COMP31212: Concurrency A Review of Java Concurrency. Giles Reger

Chapter 5: Process Synchronization. Operating System Concepts Essentials 2 nd Edition

Chapter 6: Process Synchronization. Operating System Concepts 8 th Edition,

THREADS & CONCURRENCY

CSCD 330 Network Programming

Concurrent Programming using Threads

Faculty of Computers & Information Computer Science Department

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

Roadmap. Readers-Writers Problem. Readers-Writers Problem. Readers-Writers Problem (Cont.) Dining Philosophers Problem.

Synchronization synchronization.

CSCD 330 Network Programming

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

Process Synchronization

Process Synchronization

EI 338: Computer Systems Engineering (Operating Systems & Computer Architecture)

Synchronization. CS 416: Operating Systems Design, Spring 2011 Department of Computer Science Rutgers University

Threads Questions Important Questions

Deadlock and Monitors. CS439: Principles of Computer Systems September 24, 2018

Roadmap. Tevfik Ko!ar. CSC Operating Systems Fall Lecture - XI Deadlocks - II. Louisiana State University

Threads and Locks. CSCI 5828: Foundations of Software Engineering Lecture 09 09/22/2015

Roadmap. Bounded-Buffer Problem. Classical Problems of Synchronization. Bounded Buffer 1 Semaphore Soln. Bounded Buffer 1 Semaphore Soln. Tevfik Ko!

Process Synchronization

CS370 Operating Systems

Multiple Inheritance. Computer object can be viewed as

Semaphore. Originally called P() and V() wait (S) { while S <= 0 ; // no-op S--; } signal (S) { S++; }

CS360 Lecture 12 Multithreading

CMSC 330: Organization of Programming Languages

CS 10: Problem solving via Object Oriented Programming Winter 2017

CS 361 Concurrent programming Drexel University Spring 2000 Lecture 14. The dining philosophers problem

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

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

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

Chapter 32 Multithreading and Parallel Programming

Performance Throughput Utilization of system resources

Programming Language Concepts: Lecture 11

CHAPTER 6: PROCESS SYNCHRONIZATION

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

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

Concurrency in Java Prof. Stephen A. Edwards

Threads Chate Patanothai

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

Chapter 5: Process Synchronization. Operating System Concepts 9 th Edition

Java Threads. Introduction to Java Threads

Object Oriented Programming and Design in Java. Session 18 Instructor: Bert Huang

Multithreaded Programming Part II. CSE 219 Stony Brook University, Department of Computer Science

Process Coordination

i219 Software Design Methodology 12. Case study 1 Dining philosopher problem Kazuhiro Ogata (JAIST) Outline of lecture

Synchronization in Java

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

Chapter 8 Threads Zindell Technologies, Ltd. Question 1: Which one statement below is true concerning the following code?

Silberschatz and Galvin Chapter 6

THREADS & CONCURRENCY

COMP346 Winter Tutorial 4 Synchronization Semaphores

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

Only one thread can own a specific monitor

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

Concurrency. Chapter 5

CISC 4700 L01 Network & Client-Server Programming Spring Cowell Chapter 15: Writing Threaded Applications

3C03 Concurrency: Starvation and Deadlocks

THREADS AND CONCURRENCY

Process Management And Synchronization

Concurrent Programming

Multiprocessing Threads/Lightweight objects Thread methods Concurrency Issues

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

Deadlock and Monitors. CS439: Principles of Computer Systems February 7, 2018

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

Module - 4 Multi-Threaded Programming

RACE CONDITIONS AND SYNCHRONIZATION

CS61B, Spring 2003 Discussion #17 Amir Kamil UC Berkeley 5/12/03

Memory system behavior: volatile variables. CS 361 Concurrent programming Drexel University Fall 2004 Lecture 6. Volatile variables and concurrency

Last Class: Synchronization Problems!

COMP 346 WINTER Tutorial 2 SHARED DATA MANIPULATION AND SYNCHRONIZATION

Multithreaded Programming

Transcription:

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

Announcements Exam 1 tonight 6:30 pm - 7:30 pm MTHW 210 2

Outcomes Understand race conditions Critical sections and mutual exclusion Synchronization mechanism synchronized methods, block of code wait() and notify() Understand potential problems busy waiting deadlock livelock 3

Thread Scheduling Remember Once a thread is runnable it can be scheduled at any time It is hard to predict the actual ordering With multiple threads, we must ensure that any possible interleaving of threads would still be a correct execution 4

Race Conditions If the result of a computation changes depending upon the actual ordering of threads we call it a race condition. Can occur even with very simple concurrent programs. Consider a program that simply increments a single variable, count 100000 times the task is divided among multiple threads 5

public class RaceCondition extends Thread { private static int counter = 0; public static final int THREADS = 4; public static final int COUNT = 10000000; Race Example public static void main(string[] args){ RaceCondition[] threads = new RaceCondition[THREADS]; for(int i=0;i<threads;i++) { threads[i] = new RaceCondition(); threads[i].start(); try{ for(int i=0;i<threads;i++) threads[i].join(); catch (InterruptedException e) { e.printstacktrace(); System.out.println( Counter: + counter); public void run(){ for(int i=0;i<count/threads;i++) counter++; 6

Race Without multiple threads, always correct. With multiple threads, often incorrect! Why? multiple threads modifying the same value counter++ is not atomic Atomic operations A java statement translates to multiple machine level statements the thread can be swapped in the middle of these machine level statements 7

The memory hierarchy Speed Cost Size ALU Registers Cache CPU Cache (MB) Main Memory (GB) 8

Multi Core possibility ALU Core ALU Core Registers Registers Cache CPU Cache Cache (MB) Main Memory (GB) 9

Multi Core possibility 2 ALU Core ALU Core Registers Registers CPU Cache (MB) Main Memory (GB) 10

Multi CPU possibility ALU CPU ALU Registers ALU Registers Registers Cache Cache Cache Cache (MB) Cache (MB) CPU Program Main Memory (GB) Data 11

Atomic operations and Caching Data is operated on in ALUs register = count; register++; count = register; Thus if a thread is swapped out just before the last statement, and another thread swapped in, then we have a lost update The memory hierarchy caches data values. If multiple threads are using some data, it gets copied into multiple caches this can cause different threads to not see all changes made by other threads! 12

Shared mutable state How do we ensure correct behavior? Many problems of synchronization can be traced to data that is concurrently read and written by multiple threads shared mutable state if no thread writes -- no problems For example, the variable count is shared mutable state. Only one thread should modify at a given time, and no thread should read the value during this time. 13

Critical Section A section of code that should not be accessed by multiple threads concurrently We need to guarantee mutual exclusion in these sections Java solution: use a lock that only one thread holds at a time also called a monitor any object can be locked 14

Synchronized The synchronized keyword can be used to declare a method or block of code as a critical section i.e., only one thread can be executing any statements in that method or block of code. public synchronized int methoda(){...//critical section public int methoda(){... synchronized (someobject) {... //Critical section 15

Method vs. block of code When synchronized is used with a block of code, we explicitly specify what object should be used for locking; can arbitrarily limit the critical section can have independent locks for different code. A synchronized method implicitly locks the object (this) on which the method is called the class, in the case of static methods 16

(No) Race Condition public class NoRaceCondition extends Thread { private static int counter = 0; public static final int THREADS = 4; public static Object lock = new Object(); public static final int COUNT = 1000000; public static void main(string[] args){ NoRaceCondition[] threads = new NoRaceCondition[THREADS]; for(int i=0;i<threads;i++) { threads[i] = new NoRaceCondition(); threads[i].start(); Note: lock is static. try{ for(int i=0;i<threads;i++) threads[i].join(); catch (InterruptedException e) { e.printstacktrace(); System.out.println( Counter: + counter); public void run(){ for(int i=0;i<count/threads;i++){ synchronized(noracecondition.lock){ counter++; Note: not entire method or for loop! 17

Synchronization Any code that is synchronized can only be executed by a thread that holds the appropriate lock Only one thread can hold the lock for a given object Any changes made in a critical section will be visible to all threads once they get the lock (ensured by Java) 18

Announcements No class on Monday No labs next week 19

Producer-Consumer A very common scenario a producer process creates data a consumer process processes data (and deletes it) e.g., networking, unix pipes, device drivers A shared data structure (buffer) is used to hold data before processing limited size if empty -- consumer waits if full -- produce waits 20

Producer-Consumer import java.util.*; public class ProducerConsumer extends Thread{ private static Buffer buffer = new Buffer(); private boolean isconsumer; public ProducerConsumer(boolean isc){isconsumer=isc; public static void main ( String[] args ) { ProducerConsumer consumer = new ProducerConsumer(true); ProducerConsumer producer = new ProducerConsumer(false); consumer.start(); producer.start(); try{ consumer.join(); producer.join(); catch (InterruptedException e) { e.printstacktrace(); // run method 21

public void run(){ String s; for(int i=0;i<1000;i++){ try{ if(isconsumer){ s = (String) buffer.removeitem(); System.out.println( Consumed: + s); else { s = Item + i; buffer.additem(s); System.out.println( \t\tproduced: + s); sleep(math.ceil(math.random()*10)) ; catch (InterruptedException e) { e.printstacktrace(); 22

Buffer class How should the Buffer class be implemented? The buffer is shared mutable state! We must ensure that producers and consumers do not adversely affect each other. When the producer thread is adding a new entry, the consumer should not remove an entry and vice versa. Assume: entries are all packed in the array (i.e., there are no holes) addition/deletion is done at end of array. 23

Potential Solution public class Buffer { public final static int SIZE = 10; private Object [] objects = new Object [ SIZE ]; private int count = 0; public synchronized void additem ( Object object ) { objects [ count ++] = object ; public synchronized Object removeitem () { Object object = objects [--count]; return object ; Note: typo in book! not count-- 24

Problem If we simply use synchronized methods, what should we do if buffer is full when adding, or buffer is empty when deleting? We could throw an exception and let the user handle this situation. Not a good solution. Ideally, we should wait for the other process to delete (or add) something HOW? 25

public class Buffer {... public void additem ( Object object ) { while (true) { synchronized (this) { Potential Solution 2 if ( count!= SIZE ){ objects [ count ++] = object ; break; public Object removeitem () { Object object; while (true) { synchronized(this) { if(count!= 0 ) { object = objects [--count]; break; return object ; 26

Busy-waiting! This works, but it is inefficient The thread continuously consumes resources while waiting for something to happen - called busy waiting We would like the thread to wait until some condition is true. How do we suspend a thread until some condition is potentially true? This is achieved using the wait() and notify () methods. 27

Thread States new thread start() Runnable notify() wake up Not Runnable schedule yield() (un)schedule Running sleep() wait() run() terminates uncaught exception terminated

wait(), notify(), and notifyall() These methods can be called on any object. The calling thread must own the lock (monitor) for the object When the current thread executes wait(), it becomes not runnable until the thread is woken up due to a call to notify() or notifyall() on the object on which it is waiting the thread is interrupted by some other thread the timeout interval has passed 29

The wait() method The calling thread gives up its lock on the object until it is woken up or interrupted wait() waits forever to be woken up by notify() or notifyall () wait(long timeout) waits only for timeout milliseconds wait(long timeout, int nanos) specify interval with greater accuracy When the thread waits, it gives up the lock on the object (but not other locks) The thread only resumes after it has re-acquired the lock on the object on which is called wait. 30

Notify methods Calling thread must own the lock on the object notifyall() causes all threads waiting on this object to be woken up notify() causes one (arbitrarily chosen) thread waiting on this object to be woken up Both calls result in the lock on the object to be released one of the newly woken threads will get the lock and be able to move on Repeated waits are necessary to ensure that the necessary conditions have been met 31

Producer-Consumer Solution public class Buffer { public final static int SIZE = 10; private Object [] objects = new Object [ SIZE ]; private int count = 0; public synchronized void additem ( Object object ) throws InterruptedException { while ( count == SIZE ) wait (); objects [ count ++] = object ; notifyall (); public synchronized Object removeitem () throws InterruptedException { while ( count == 0 ) wait (); Object object = objects [--count]; notifyall (); return object ; 32

Synchronization Examples 33

Bank Account Example Create a multi-threaded banking class. Allow threads to deposit; withdraw; getbalance Only one thread should be modifying balance at any time. Multiple threads can be reading balance at the same time. 34

Solution Keep a count of current active readers All access to readers is synchronized on the account object. Changes to balance are made only in the changebalance() method which is synchronized on the account object. can only change if there are no current readers note: wait() until this is true note: readers must notify() when done! 35

SynchronizedAccount public class SynchronizedAccount { private double balance = 0.0; private int readers = 0; public double getbalance () throws InterruptedException { double amount ; synchronized ( this ) { readers ++; amount = balance ; synchronized ( this ) { if( --readers == 0 ) notifyall (); return amount ; public void deposit ( double amount ) throws InterruptedException { changebalance ( amount ); System.out. println (" Deposited $" + amount + "." );... 36

SynchronizedAccount public boolean withdraw ( double amount ) throws InterruptedException { boolean success = changebalance ( -amount ); if( success ) System.out.println (" Withdrew $" + amount + "." ) ; else System.out.println (" Failed to withdraw $" + amount + ": insufficient funds." ); return success ; private synchronized boolean changebalance ( double amount ) throws InterruptedException { boolean success ; while ( readers > 0 ) wait (); if( success = ( balance + amount > 0) ) balance += amount ; return success ; 37

Account tester public class TestSynchronizedAccount extends Thread { static final int THREADS = 10; static SynchronizedAccount account = new SynchronizedAccount(); static TestSynchronizedAccount[] threads = new TestSynchronizedAccount[THREADS]; static double netchange[] = new double[threads]; int threadid; public TestSynchronizedAccount(int id) { threadid=id; public static void main(string[] args) { double totalchange=0; try{ for(int i=0;i<threads;i++) { threads[i] = new TestSynchronizedAccount(i); threads[i].start(); for(int i=0;i<threads;i++){ threads[i].join(); totalchange+=netchange[i]; System.out.println("Net Change: " + totalchange + "\tcurrent Balance: "+ account.getbalance()); catch (InterruptedException e) { e.printstacktrace(); 38

Account tester (cont.) public void run(){ double totalwithdrawals=0; double amount; try{ for(int i=0;i<10;i++) { amount = (Math.ceil(Math.random()*10000))/100.0; if(math.random() <0.5) { if(testsynchronizedaccount.account.withdraw(amount)) { netchange[i]-=amount; System.out.println("\t\t\tThread " + i + " Withdrew: " + amount); else { TestSynchronizedAccount.account.deposit(amount); netchange[i]+=amount; System.out.println("\t\t\tThread " + i + " Deposited: " + amount); catch (InterruptedException e) { e.printstacktrace(); 39

Starvation, Livelock, Deadlock It is possible for the changebalance() method to always be prevented from running by some checkbalance() method Thus deposit/withdrawal can starve A deadlock is a situation where more than one threads are waiting for each other in a circular fashion -- none of them will ever make progress! Another potential problem is livelock, i.e., some thread(s) is making progress, but some others may be blocked indefinitely 40

The Dining Philosophers Consider N philosophers that think and eat There is a circular table with N seats and N chopsticks When a philosopher wants to eat she tries to pick up two chopsticks and then eats Once done eating she replaces (after washing of course) the chopsticks. How do we simulate this? There should be no starving philosopher! 41

Dining Philosopher (deadlock) public void DeadlockPhilosopher extends Thread { public static final int SEATS = 5; private static boolean [] chopsticks = new boolean [SEATS]; private int seat ; public DeadlockPhilosopher ( int seat ) { this.seat = seat ; public void run () { try { getchopstick ( seat ); Thread.sleep (50) ; getchopstick ( seat - 1 ); catch ( InterruptedException e ) { e. printstacktrace (); eat (); 42

Dining Philosophers (cont.) private void getchopstick ( int location ) throws InterruptedException { if( location < 0 ) location += SEATS ; synchronized ( chopsticks ) { while ( chopsticks [ location ] ) chopsticks.wait (); chopsticks [ location ] = true ; System. out. println (" Philosopher " + seat + " picked up chopstick " + location + "."); private void eat () { // done eating, put back chopsticks synchronized ( chopsticks ) { chopsticks [ seat ] = false ; if( seat == 0) chopsticks [ SEATS - 1] = false ; else chopsticks [ seat - 1] = false ; chopsticks.notifyall (); 43

Dining Philosophers (Good) import java.util.*; public class DiningPhilosopher2 extends Thread { public static final int SEATS = 5; private static boolean [] chopsticks = new boolean [ SEATS ]; private int seat ; public DiningPhilosopher2 ( int seat ) { this.seat = seat; public static void main ( String args []) { for ( int i = 0; i < SEATS ; i++ ) chopsticks [i] = false ; DiningPhilosopher2 [] philosophers = new DiningPhilosopher2 [ SEATS ]; for ( int i = 0; i < SEATS ; i++ ) { philosophers [i] = new DiningPhilosopher2 ( i ); philosophers[i].start (); try { for ( int i = 0; i < SEATS ; i++ ) philosophers[i].join (); catch ( InterruptedException e ) { e.printstacktrace (); System.out.println ("All philosophers done."); 44

public void run () { for ( int i = 0; i < 100; i++ ) { think (); getchopsticks (); eat (); private void think () { Random random = new Random (); try { sleep ( random. nextint (20) + 10 ); catch ( InterruptedException e ) { e. printstacktrace (); private void eat () { // eat rice first synchronized ( chopsticks ) { chopsticks [ seat ] = false ; if( seat == 0) chopsticks [ SEATS - 1] = false ; else chopsticks [ seat - 1] = false ; chopsticks. notifyall (); 45

private void getchopsticks () { int location1 = seat ; int location2 ; if( seat == 0 ) location2 = SEATS - 1; else location2 = seat - 1; synchronized ( chopsticks ) { while ( chopsticks [ location1 ] chopsticks [ location2 ] ) { try { chopsticks. wait (); catch ( InterruptedException e ) { e. printstacktrace (); chopsticks [ location1 ] = true ; chopsticks [ location2 ] = true ; System.out.println (" Philosopher " + seat + " picked up chopsticks " + location1 + " and " + location2 + "."); 46