Anthony D. Joseph and John Canny

Slides:



Advertisements
Similar presentations
CS162 Operating Systems and Systems Programming Lecture 5 Cooperating Threads September 14, 2005 Prof. John Kubiatowicz
Advertisements

CSE451 Processes Spring 2001 Gary Kimura Lecture #4 April 2, 2001.
Processes April 5, 2000 Instructor: Gary Kimura Slides courtesy of Hank Levy.
Process Concept An operating system executes a variety of programs
Threads CS 416: Operating Systems Design, Spring 2001 Department of Computer Science Rutgers University
Chapter 4: Threads. From Processes to Threads 4.3 Silberschatz, Galvin and Gagne ©2005 Operating System Concepts – 7 th edition, Jan 23, 2005 Threads.
Threads Many software packages are multi-threaded Web browser: one thread display images, another thread retrieves data from the network Word processor:
Implementing Processes and Process Management Brian Bershad.
COSC 3407: Operating Systems Lecture 5: Independent Vs. Cooperating Threads.
Lecture 3 Process Concepts. What is a Process? A process is the dynamic execution context of an executing program. Several processes may run concurrently,
CSC139 Operating Systems Lecture 4 Thread Dispatching Adapted from Prof. John Kubiatowicz's lecture notes for CS162
CS 162 Discussion Section Week 2. Who am I? Haoyuan (HY) Li Office Hours: 1pm-3pm
CS 162 Discussion Section Week 2. Who am I? Wesley Chow Office Hours: 12pm-2pm 411 Soda Does Monday 1-3 work for everyone?
CS162 Operating Systems and Systems Programming Lecture 3 Concurrency and Thread Dispatching September 7 th, 2011 Anthony D. Joseph and Ion Stoica
CPS110: Implementing threads Landon Cox. Recap and looking ahead Hardware OS Applications Where we’ve been Where we’re going.
Chapter 4: Threads March 17 th, 2009 Instructor: Hung Q. Ngo Kyung Hee University.
Lecture 5: Threads process as a unit of scheduling and a unit of resource allocation processes vs. threads what to program with threads why use threads.
CS 162 Discussion Section Week 2 (9/16 – 9/20). Who am I? Kevin Klues Office Hours:
1 Computer Systems II Introduction to Processes. 2 First Two Major Computer System Evolution Steps Led to the idea of multiprogramming (multiple concurrent.
Operating Systems CSE 411 CPU Management Sept Lecture 10 Instructor: Bhuvan Urgaonkar.
Department of Computer Science and Software Engineering
CS162 Operating Systems and Systems Programming Lecture 2 Synchronization January 26 th, 2011 Ion Stoica
Goals for Today How do we provide multiprogramming? What are Processes? How are they related to Threads and Address Spaces? Note: Some slides and/or pictures.
1 Module 3: Processes Reading: Chapter Next Module: –Inter-process Communication –Process Scheduling –Reading: Chapter 4.5, 6.1 – 6.3.
CS 162 Discussion Section Week 2. Who am I? Prashanth Mohan Office Hours: 11-12pm Tu W at.
Silberschatz, Galvin and Gagne ©2009 Operating System Concepts – 8 th Edition, Chapter 4: Threads.
Threads & Multithreading
Processes and threads.
Process concept.
CSCI 511 Operating Systems Chapter 3,4 (Part A) Processes and Threads
Process Management Process Concept Why only the global variables?
CS 6560: Operating Systems Design
CSCI 511 Operating Systems Ch3, 4 (Part C) Cooperating Threads
CSCS 511 Operating Systems Ch3, 4 (Part B) Further Understanding Threads Dr. Frank Li Skipped sections 3.5 & 3.6 
Lecture Topics: 11/1 Processes Process Management
Chapter 2 Processes and Threads Today 2.1 Processes 2.2 Threads
Process Management Presented By Aditya Gupta Assistant Professor
Intro to Processes CSSE 332 Operating Systems
CS162 Operating Systems and Systems Programming Lecture 4 Cooperating Threads February 4, 2008 Prof. Anthony D. Joseph
CS162 Operating Systems and Systems Programming Lecture 5 Cooperating Threads September 15, 2010 Prof. John Kubiatowicz
February 2, 2009 Ion Stoica CS162 Operating Systems and Systems Programming Lecture 5 Cooperating Threads February.
CS162 Operating Systems and Systems Programming Lecture 3 Concurrency and Thread Dispatching January 30, 2013 Anthony D. Joseph
Threads & multithreading
Chapter 4: Threads.
Concurrency: Threads, Address Spaces, and Processes
Process management Information maintained by OS for process management
CSCI 511 Operating Systems Ch3, 4 (Part B) Further Understanding Threads Dr. Frank Li Skipped sections 3.5 & 3.6 
CS162 Operating Systems and Systems Programming Lecture 4 Thread Dispatching September 13, 2010 Prof. John Kubiatowicz
CS162 Operating Systems and Systems Programming Lecture 3 Thread Dispatching January 30, 2008 Prof. Anthony D. Joseph
CSCI 511 Operating Systems Chapter 3,4 (Part A) Processes and Threads
CSCI 511 Operating Systems Ch3, 4 (Part C) Cooperating Threads
ICS 143 Principles of Operating Systems
Concurrency: Threads, Address Spaces, and Processes
More examples How many processes does this piece of code create?
January 28, 2010 Ion Stoica CS162 Operating Systems and Systems Programming Lecture 4 Thread Dispatching January.
Process & its States Lecture 5.
Process Description and Control
CS162 Operating Systems and Systems Programming Lecture 5 Cooperating Threads September 15, 2008 Prof. John Kubiatowicz
Lecture Topics: 11/1 General Operating System Concepts Processes
Processes Hank Levy 1.
Processes and Process Management
October 9, 2002 Gary Kimura Lecture #5 October 9, 2002
Anthony D. Joseph and Ion Stoica
Operating Systems: A Modern Perspective, Chapter 6
Anthony D. Joseph and Ion Stoica
Chapter 2 Processes and Threads 2.1 Processes 2.2 Threads
CS510 Operating System Foundations
Processes Hank Levy 1.
CS703 – Advanced Operating Systems
Concurrency: Threads, Address Spaces, and Processes
Presentation transcript:

Anthony D. Joseph and John Canny CS162 Operating Systems and Systems Programming Lecture 3 Concurrency and Thread Dispatching September 11, 2013 Anthony D. Joseph and John Canny http://inst.eecs.berkeley.edu/~cs162

Goals for Today Review: Processes and Threads Thread Dispatching Cooperating Threads Concurrency examples Note: Some slides and/or pictures in the following are adapted from slides ©2005 Silberschatz, Galvin, and Gagne. Slides courtesy of Anthony D. Joseph, John Kubiatowicz, AJ Shankar, George Necula, Alex Aiken, Eric Brewer, Ras Bodik, Ion Stoica, Doug Tygar, and David Wagner.

Why Processes & Threads? Multiprogramming: Run multiple applications concurrently Protection: Don’t want a bad application to crash system! Goals: Process: unit of execution and allocation Virtual Machine abstraction: give process illusion it owns machine (i.e., CPU, Memory, and IO device multiplexing) Solution: Multiprogramming: Older idea than multi-tasking, run jobs concurrently (load several into memory), but not necessarily “interactively”. Process creation & switching expensive Need concurrency within same app (e.g., web server) Challenge: Thread: Decouple allocation and execution Run multiple threads within same process Solution:

Putting it together: Process (Unix) Process A(int tmp) { if (tmp<2) B(); printf(tmp); } B() { C(); C() { A(2); A(1); … Memory Resources Stack I/O State (e.g., file, socket contexts) Sequential stream of instructions Stored in OS CPU state (PC, SP, registers..)

Putting it together: Processes Process N Switch overhead: high CPU state: low Memory/IO state: high Process creation: high Protection CPU: yes Memory/IO: yes Sharing overhead: high (involves at least a context switch) CPU state IO Mem. CPU state IO Mem. CPU state IO Mem. … CPU sched. OS 1 process at a time CPU (1 core)

Putting it together: Threads Process 1 Process N threads threads Switch overhead: low (only CPU state) Thread creation: low Protection CPU: yes Memory/IO: No Sharing overhead: low (thread switch overhead low) Mem. Mem. IO state … IO state … … CPU state CPU state CPU state CPU state CPU sched. OS 1 thread at a time CPU (1 core)

Putting it together: Multi-Cores Process 1 Process N threads threads Switch overhead: low (only CPU state) Thread creation: low Protection CPU: yes Memory/IO: No Sharing overhead: low (thread switch overhead low) Mem. Mem. IO state … IO state … … CPU state CPU state CPU state CPU state CPU sched. OS 4 threads at a time core 1 Core 2 Core 3 Core 4 CPU

Putting it together: Hyper-Threading Process 1 Process N threads threads Switch overhead between hardware-threads: very-low (done in hardware) Contention for ALUs/FPUs may hurt performance Mem. Mem. IO state … IO state … … CPU state CPU state CPU state CPU state CPU sched. OS hardware-threads (hyperthreading) 8 threads at a time core 1 core 2 core 3 core 4 CPU

Process Control Block The current state of process held in a process control block (PCB): (for a single-threaded process) Process Control Block

CPU Switch From Process to Process This is also called a “context switch” Code executed in kernel above is overhead Overhead sets minimum practical switching time Less overhead with SMT/Hyperthreading, but… contention for resources instead

The Numbers Context switch in Linux: 3-4 secs (Current Intel i7 & E5). Some surprises: Thread switching only slightly faster than process switching (100 ns). But switching across cores about 2x more expensive than within-core switching. Context switch time increases sharply with the size of the working set*, and can increase 100x or more. * The working set is the subset of memory used by the process in a time window. Moral: Context switching depends mostly on cache limits and the process or thread’s hunger for memory.

The Numbers Many process are multi-threaded, so thread context switches may be either within-process or across-processes. The latter involve changes in memory and I/O tables and are more like single-threaded process switches described earlier.

Classification Real operating systems have either Many One # of addr spaces: Many One # threads per AS: MS/DOS, early Macintosh Traditional UNIX Embedded systems (Geoworks, VxWorks, JavaOS,etc) JavaOS, Pilot(PC) Mach, OS/2, Linux Win NT to 8, Solaris, HP-UX, OS X Real operating systems have either One or many address spaces One or many threads per address space

Thread State State shared by all threads in process/addr space Content of memory (global variables, heap) I/O state (file system, network connections, etc) State “private” to each thread Kept in TCB  Thread Control Block CPU registers (including, program counter) Execution stack – what is this? Execution Stack Parameters, temporary variables Return PCs are kept while called procedures are executing

Review: Execution Stack Example A(int tmp) { if (tmp<2) B(); printf(tmp); } B() { C(); C() { A(2); A(1); exit; addrX: . addrY: . addrU: . Stack holds function arguments, return address Permits recursive execution Crucial to modern languages addrV: . addrZ:

Review: Execution Stack Example A(int tmp) { if (tmp<2) B(); printf(tmp); } B() { C(); C() { A(2); A(1); exit; A: tmp=1 ret=addrZ addrX: Stack Pointer . Stack Growth addrY: . addrU: . Stack holds function arguments, return address Permits recursive execution Crucial to modern languages addrV: . addrZ:

Review: Execution Stack Example A(int tmp) { if (tmp<2) B(); printf(tmp); } B() { C(); C() { A(2); A(1); exit; A: tmp=1 ret=addrZ addrX: Stack Pointer . Stack Growth addrY: . addrU: . Stack holds function arguments, return address Permits recursive execution Crucial to modern languages addrV: . addrZ:

Review: Execution Stack Example A(int tmp) { if (tmp<2) B(); printf(tmp); } B() { C(); C() { A(2); A(1); exit; A: tmp=1 ret=addrZ addrX: Stack Pointer . Stack Growth addrY: . addrU: . Stack holds function arguments, return address Permits recursive execution Crucial to modern languages addrV: . addrZ:

Review: Execution Stack Example A(int tmp) { if (tmp<2) B(); printf(tmp); } B() { C(); C() { A(2); A(1); exit; A: tmp=1 ret=addrZ addrX: . B: ret=addrY Stack Pointer addrY: . Stack Growth addrU: . Stack holds function arguments, return address Permits recursive execution Crucial to modern languages addrV: . addrZ:

Review: Execution Stack Example A(int tmp) { if (tmp<2) B(); printf(tmp); } B() { C(); C() { A(2); A(1); exit; A: tmp=1 ret=addrZ addrX: . B: ret=addrY Stack Pointer addrY: . Stack Growth addrU: . Stack holds function arguments, return address Permits recursive execution Crucial to modern languages addrV: . addrZ:

Review: Execution Stack Example A(int tmp) { if (tmp<2) B(); printf(tmp); } B() { C(); C() { A(2); A(1); exit; A: tmp=1 ret=addrZ addrX: . B: ret=addrY C: ret=addrU addrY: Stack Pointer . Stack Growth addrU: . Stack holds function arguments, return address Permits recursive execution Crucial to modern languages addrV: . addrZ:

Review: Execution Stack Example A(int tmp) { if (tmp<2) B(); printf(tmp); } B() { C(); C() { A(2); A(1); exit; A: tmp=1 ret=addrZ addrX: . B: ret=addrY C: ret=addrU addrY: Stack Pointer . Stack Growth addrU: . Stack holds function arguments, return address Permits recursive execution Crucial to modern languages addrV: . addrZ:

Review: Execution Stack Example A(int tmp) { if (tmp<2) B(); printf(tmp); } B() { C(); C() { A(2); A(1); exit; A: tmp=1 ret=addrZ addrX: . B: ret=addrY C: ret=addrU addrY: . A: tmp=2 ret=addrV Stack Pointer Stack Growth addrU: . Stack holds function arguments, return address Permits recursive execution Crucial to modern languages addrV: . addrZ:

Review: Execution Stack Example A(int tmp) { if (tmp<2) B(); printf(tmp); } B() { C(); C() { A(2); A(1); exit; A: tmp=1 ret=addrZ addrX: . B: ret=addrY C: ret=addrU addrY: . A: tmp=2 ret=addrV Stack Pointer Stack Growth addrU: . Stack holds function arguments, return address Permits recursive execution Crucial to modern languages addrV: . addrZ:

Review: Execution Stack Example A(int tmp) { if (tmp<2) B(); printf(tmp); } B() { C(); C() { A(2); A(1); exit; A: tmp=1 ret=addrZ addrX: . B: ret=addrY C: ret=addrU addrY: . A: tmp=2 ret=addrV Stack Pointer Stack Growth addrU: . Output: 2 addrV: . addrZ:

Review: Execution Stack Example A(int tmp) { if (tmp<2) B(); printf(tmp); } B() { C(); C() { A(2); A(1); exit; A: tmp=1 ret=addrZ addrX: . B: ret=addrY C: ret=addrU addrY: Stack Pointer . Stack Growth addrU: . Output: 2 addrV: . addrZ:

Review: Execution Stack Example A(int tmp) { if (tmp<2) B(); printf(tmp); } B() { C(); C() { A(2); A(1); exit; A: tmp=1 ret=addrZ addrX: . B: ret=addrY Stack Pointer addrY: . Stack Growth addrU: . Output: 2 addrV: . addrZ:

Review: Execution Stack Example A(int tmp) { if (tmp<2) B(); printf(tmp); } B() { C(); C() { A(2); A(1); exit; A: tmp=1 ret=addrZ addrX: Stack Pointer . Stack Growth addrY: . addrU: . Output: 2 1 addrV: . addrZ:

Review: Execution Stack Example A(int tmp) { if (tmp<2) B(); printf(tmp); } B() { C(); C() { A(2); A(1); exit; addrX: . addrY: . addrU: . Output: 2 1 addrV: . addrZ:

Single-Threaded Example Imagine the following C program: main() { ComputePI(“pi.txt”); PrintClassList(“clist.text”); } What is the behavior here? Program would never print out class list Why? ComputePI would never finish Compute all the digits of PI, save into file “pi.txt”

Use of Threads Version of program with Threads: main() { CreateThread(ComputePI(“pi.txt”)); CreateThread(PrintClassList(“clist.text”)); } What does “CreateThread” do? Start independent thread running given procedure What is the behavior here? Now, you would actually see the class list This should behave as if there are two separate CPUs CPU1 CPU2 Time

Memory Footprint of Two-Thread Example If we stopped this program and examined it with a debugger, we would see Two sets of CPU registers Two sets of Stacks Questions: How do we position stacks relative to each other? What maximum size should we choose for the stacks? What happens if threads violate this? How might you catch violations? Code Global Data Heap Stack 1 Stack 2 Address Space

Per Thread State Each Thread has a Thread Control Block (TCB) Execution State: CPU registers, program counter (PC), pointer to stack (SP) Scheduling info: state, priority, CPU time Various Pointers (for implementing scheduling queues) Pointer to enclosing process (PCB) Etc (add stuff as you find a need) OS Keeps track of TCBs in protected memory In Array, or Linked List, or …

Multithreaded Processes PCB points to multiple TCBs: Switching threads within a block is a simple thread switch Switching threads across blocks requires changes to memory and I/O address tables.

Lifecycle of a Thread (or Process) As a thread executes, it changes state: new: The thread is being created ready: The thread is waiting to run running: Instructions are being executed waiting: Thread waiting for some event to occur terminated: The thread has finished execution “Active” threads are represented by their TCBs TCBs organized into queues based on their state

Ready Queues Note because of the actual number of live threads in a typical OS, and the (much smaller) number of running threads, most threads will be in a “ready” state. Thread not running  TCB is in some scheduler queue

Ready Queue And Various I/O Device Queues Thread not running  TCB is in some scheduler queue Separate queue for each device/signal/condition Each queue can have a different scheduler policy Head Tail Ready Queue SSD Unit 0 Disk Unit 2 Ether Netwk 0 Other State TCB9 Link Registers TCB6 TCB16 Other State TCB2 Link Registers TCB3 Other State TCB8 Link Registers

Administrivia: Project Signup Project Signup: Use “Group/Section Signup” Link 4-5 members to a group, everyone must attend the same section Use Piazza pinned teammate search thread (please close when done!) Only submit once per group! Due Thu (9/12) by 11:59PM Everyone in group must have logged into their cs162-xx accounts once before you register the group, Select at least 3 potential sections New section assignments: Watch “Group/Section Assignment” Link Attend new sections NEXT week Section Time Location TA 101 Tu 9:00A-10:00A 310 Soda Matt 102 Tu 10:00A-11:00A 75 Evans 103 Tu 11:00A-12:00P 71 Evans George 104 Tu 3:00P-4:00P 24 Wheeler 105 We 10:00A-11:00A 85 Evans Kevin 106 We 11:00A-12:00P 107 Tu 1:00P-2:00P 405 Soda Allen 108 Tu 2:00P-3:00P

5min Break

Dispatch Loop Conceptually, the dispatching loop of the operating system looks as follows: Loop { RunThread(); ChooseNextThread(); SaveStateOfCPU(curTCB); LoadStateOfCPU(newTCB); } This is an infinite loop One could argue that this is all that the OS does Emergency crash of operating system called “panic()”

Running a thread Consider first portion: RunThread() How do I run a thread? Load its state (registers, stack pointer) into CPU Load environment (virtual memory space, etc) Jump to the PC How does the dispatcher get control back? Internal events: thread returns control voluntarily External events: thread gets preempted

Yielding through Internal Events Blocking on I/O The act of requesting I/O implicitly yields the CPU Waiting on a “signal” from other thread Thread asks to wait and thus yields the CPU Thread executes a yield() Thread volunteers to give up CPU computePI() { while(TRUE) { ComputeNextDigit(); yield(); } Note that yield() must be called by programmer frequently enough!

Stack for Yielding a Thread ComputePI User Stack Kernel Stack yield run_new_thread kernel_yield Trap to OS switch How do we run a new thread? run_new_thread() { newThread = PickNewThread(); switch(curThread, newThread); ThreadHouseKeeping(); /* deallocates finished threads */ } Finished thread not killed right away. Why? Move them in “exit/terminated” state ThreadHouseKeeping() deallocates finished threads

Stack for Yielding a Thread ComputePI User Stack Kernel Stack yield run_new_thread kernel_yield Trap to OS switch How do we run a new thread? run_new_thread() { newThread = PickNewThread(); switch(curThread, newThread); ThreadHouseKeeping(); /* deallocates finished threads */ } How does dispatcher switch to a new thread? Save anything next thread may trash: PC, regs, SP Maintain isolation for each thread

Review: Two Thread Yield Example Consider the following code blocks: proc A() { B(); } proc B() { while(TRUE) { yield(); Suppose we have two threads: Threads S and T Thread S A B(while) yield run_new_thread switch kernel_yield Thread T A B(while) yield run_new_thread switch kernel_yield

Detour: Interrupt Controller Interrupt Mask Priority Encoder IntID CPU Interrupt Int Disable Timer NMI Control Software Interrupt Network Interrupts invoked with interrupt lines from devices Interrupt controller chooses interrupt request to honor Mask enables/disables interrupts Priority encoder picks highest enabled interrupt Software Interrupt Set/Cleared by Software Interrupt identity specified with ID line CPU can disable all interrupts with internal flag Non-maskable interrupt line (NMI) can’t be disabled

Review: Preemptive Multithreading Use the timer interrupt to force scheduling decisions Timer Interrupt routine: TimerInterrupt() { DoPeriodicHouseKeeping(); run_new_thread(); } This is often called preemptive multithreading, since threads are preempted for better scheduling Solves problem of user who doesn’t insert yield(); Some Routine User Stack Kernel Stack run_new_thread TimerInterrupt Interrupt switch

Why allow cooperating threads? People cooperate; computers help/enhance people’s lives, so computers must cooperate By analogy, the non-reproducibility/non-determinism of people is a notable problem for “carefully laid plans” Advantage 1: Share resources One computer, many users One bank balance, many ATMs What if ATMs were only updated at night? Embedded systems (robot control: coordinate arm & hand) Advantage 2: Speedup Overlap I/O and computation Multiprocessors – chop up program into parallel pieces Advantage 3: Modularity Chop large problem up into simpler pieces To compile, for instance, gcc calls cpp | cc1 | cc2 | as | ld Makes system easier to extend

Threaded Web Server Multithreaded version: serverLoop() { connection = AcceptCon(); ThreadCreate(ServiceWebPage(),connection); } Advantages of threaded version: Can share file caches kept in memory, results of CGI scripts, other things Threads are much cheaper to create than processes, so this has a lower per-request overhead What if too many requests come in at once?

Thread Pools Problem with previous version: Unbounded Threads When web-site becomes too popular – throughput sinks Instead, allocate a bounded “pool” of threads, representing the maximum level of multiprogramming Master Thread Thread Pool queue slave(queue) { while(TRUE) { con=Dequeue(queue); if (con==null) sleepOn(queue); else ServiceWebPage(con); } } master() { allocThreads(slave,queue); while(TRUE) { con=AcceptCon(); Enqueue(queue,con); wakeUp(queue); } }

ATM Bank Server ATM server problem: Service a set of requests Do so without corrupting database Don’t hand out too much money

ATM bank server example Suppose we wanted to implement a server process to handle requests from an ATM network: BankServer() { while (TRUE) { ReceiveRequest(&op, &acctId, &amount); ProcessRequest(op, acctId, amount); } } ProcessRequest(op, acctId, amount) { if (op == deposit) Deposit(acctId, amount); else if … } Deposit(acctId, amount) { acct = GetAccount(acctId); /* may use disk I/O */ acct->balance += amount; StoreAccount(acct); /* Involves disk I/O */ } How could we speed this up? More than one request being processed at once Multiple threads (multi-proc, or overlap comp and I/O)

Can Threads Help? One thread per request! Requests proceeds to completion, blocking as required: Deposit(acctId, amount) { acct = GetAccount(actId); /* May use disk I/O */ acct->balance += amount; StoreAccount(acct); /* Involves disk I/O */ } Unfortunately, shared state can get corrupted: Thread 1 Thread 2 load r1, acct->balance load r1, acct->balance add r1, amount2 store r1, acct->balance add r1, amount1 store r1, acct->balance

Problem is at the lowest level Most of the time, threads are working on separate data, so scheduling doesn’t matter: Thread A Thread B x = 1; y = 2; However, What about (Initially, y = 12): x = y+1; y = y*2; What are the possible values of x? x = 1; x = y+1; y = 2; y = y*2 X could be (13, 5, 3) x=13

Problem is at the lowest level Most of the time, threads are working on separate data, so scheduling doesn’t matter: Thread A Thread B x = 1; y = 2; However, What about (Initially, y = 12): x = y+1; y = y*2; What are the possible values of x? y = 2; y = y*2; x = 1; x = y+1; X could be (13, 5, 3) x=5

Problem is at the lowest level Most of the time, threads are working on separate data, so scheduling doesn’t matter: Thread A Thread B x = 1; y = 2; However, What about (Initially, y = 12): x = y+1; y = y*2; What are the possible values of x? y = 2; x = 1; x = y+1; y= y*2; X could be (13, 5, 3) x=3

Summary Concurrent threads are a very useful abstraction Allow transparent overlapping of computation and I/O Allow use of parallel processing when available Concurrent threads introduce problems when accessing shared data Programs must be insensitive to arbitrary interleavings Without careful design, shared variables can become completely inconsistent Next lecture: deal with concurrency problems