Notes on Threads and Synchronization - Slides | CMSC 433, Study notes of Programming Languages

Material Type: Notes; Professor: Memon; Class: PROG LANG TECH & PDGMS; Subject: Computer Science; University: University of Maryland; Term: Unknown 1989;

Typology: Study notes

Pre 2010

Uploaded on 02/13/2009

koofers-user-t98
koofers-user-t98 🇺🇸

10 documents

1 / 14

Toggle sidebar

This page cannot be seen from the preview

Don't miss anything!

bg1
1
CMSC 433 – Programming Language
Technologies and Paradigms
Spring 2007
Threads and Synchronization
May 8, 2007
2
Computation Abstractions
CPU 1 CPU 2
p3p1 p2 p4
t1
t2
t1
t2
t3
t1
t4
t5
A computer
Processes
(e.g., JVM’s)
Threads
3
Processes vs. Threads
int x;
foo() {
…x…
}
int x;
foo() {
…x…
}
int x;
foo() {
…x…
}
foo() {
…x…
}
Processes do not
share data Threads share data
within a process
fork() in C 4
So, What Is a Thread?
Conceptually: it is a parallel computation
occurring within a process
Implementation view: it’s a program
counter and a stack. The heap and static
area are shared among all threads
All programs have at least one thread
(main)
pf3
pf4
pf5
pf8
pf9
pfa
pfd
pfe

Partial preview of the text

Download Notes on Threads and Synchronization - Slides | CMSC 433 and more Study notes Programming Languages in PDF only on Docsity!

CMSC 433 – Programming Language

Technologies and Paradigms

Spring 2007

Threads and Synchronization

May 8, 2007

2

Computation Abstractions

CPU 1

CPU 2

p

p

p

p

t t

t t

t

t

t t

A computer

Threads(e.g., JVM’s)Processes

3

Processes vs. Threads

}…x…foo() { int x;

}…x…foo() {int x;

int (^) x;

foo() { …x…

}

foo()

(^) {

}…x…

share data Processes do not

within a processThreads share data

fork() in C

4

So, What Is a Thread?

Conceptually

: it is a parallel computation

occurring within a process

Implementation view

: it’s a program

area are shared among all threadscounter and a stack. The heap and static

• All programs have at least one thread

(main)

5

Why Multiple Threads?

• Performance:

  • Concurrency of computation and I/O– Parallelism on multiprocessors

• Can easily express some programming

– Simulations– Event processingparadigms

• Keep computations separate, as in an OS

6

Why Not Multiple Threads?

• Overhead• Complexity

  • Higher resource usage

7

Programming Threads

• Threads are available in many languages

  • C, C++, Objective Caml, Java, SmallTalk …

• In many languages (e.g., C and C++),

– Not part of the language specificationthreads are a platform specific add-on

• Part of the Java language specification

8

Java Threads

• Every application has at least one thread

  • The “main” thread, started by the JVM to run

the application’s

main()

method.

• The code executed by

main()

can create

– Explicitly, using theother threads

Thread

class

  • Implicitly, by calling libraries that create
  • RMI, AWT/Swing, Applets, etc.threads as a consequence

13

Thread Scheduling

• Once a new thread is created, how does it

interact with existing threads?

• This is a question of scheduling:

  • Given N processors and M threads, which

thread(s) should be run at any given time?

14

Thread Scheduling

• OS schedules a single-threaded process on a

single processor

• Multithreaded process scheduling:

  • One thread per processor
  • Exploits hardware-level concurrency• Effectively splits a process across CPU’s
  • Many threads per processor
  • Need to share CPU in slices of time

15

Scheduling Example (1)

CPU 2 CPU 1

p2 p1 p2 p

One process per CPU

p2 threads:

p1 threads:

16

Scheduling Example (2)

CPU 2 CPU 1

p2 p1 p2 p

Threads shared between CPU’s

p2 threads:

p1 threads:

17

Scheduling Consequences

• Concurrency

  • Different threads from the same application can

be running

at the same time

on different

processors

• Interleaving

  • Threads can be

pre-empted

at any time

in

order to schedule other threads

18

Thread Scheduling

  • What thread to run next– When the current thread should stop runningWhen multiple threads share a CPU, must decide:

A thread can voluntarily

yield()

the CPU

  • Call to yield may be ignored; don’t depend on it

Preemptive schedulers

can de-schedule the current

  • Not all JVMs use preemptive scheduling, so a threadthread at any time stuck in a loop may

(^) never

(^) yield by itself. Therefore,

put (^) yield()

(^) into loops

(e.g., on a lock or on I/O) or go to sleepThreads are de-scheduled whenever they block

19

Thread Lifecycle

• While a thread executes, it goes through a

– number of different phases

New

: created but not yet started

Runnable

: is running, or can run on a free CPU

Blocked

: waiting for I/O or on a lock

Sleeping

: paused for a user-specified interval

Terminated

: completed

20

Which Thread to Run Next?

  • They finished sleeping, etc.– I/O became available– A lock was releasedincluding threads that were unblocked becauseThe scheduler looks at all of the runnable threads,

This can be set withOf these threads, it considers the thread’s priority.

setPriority().

Higher priority

  • Oftentimes, threads waiting for I/O are also preferred.threads get preference.

25

Data Race Example

t1.run() { static int cnt = 0; cnt = y + 1;int y = cnt;

t2.run() {} cnt = y + 1;int y = cnt;

cnt = 0

global count.run. Each will increment the Start: both threads ready to Shared state

26

Data Race Example

t1.run() { static int cnt = 0; cnt = y + 1;int y = cnt;

t2.run() {} cnt = y + 1;int y = cnt;

cnt = 0

the global counter value into y. T1 executes, grabbing Shared state

y = 0

27

Data Race Example

t1.run() { static int cnt = 0; cnt = y + 1;int y = cnt;

t2.run() {} cnt = y + 1;int y = cnt;

cnt = 1

counter value T1 executes again, storing the Shared state

y = 0

28

Data Race Example

t1.run() { static int cnt = 0; cnt = y + 1;int y = cnt;

t2.run() {} cnt = y + 1;int y = cnt;

cnt = 1

counter value into y.grabbing the global T1 finishes. T2 executes, Shared state

y = 1 y = 0

29

Data Race Example

t1.run() { static int cnt = 0; cnt = y + 1;int y = cnt;

t2.run() {} cnt = y + 1;int y = cnt;

cnt = 2

incremented cnt value. T2 executes, storing the Shared state

y = 1 y = 0

30

But When I Run it Again?

31

Data Race Example

t1.run() { static int cnt = 0; cnt = y + 1;int y = cnt;

t2.run() {} cnt = y + 1;int y = cnt;

cnt = 0

global count.run. Each will increment the Start: both threads ready to Shared state

32

Data Race Example

t1.run() { static int cnt = 0; cnt = y + 1;int y = cnt;

t2.run() {} cnt = y + 1;int y = cnt;

cnt = 0

the global counter value into y. T1 executes, grabbing Shared state

y = 0

37

Question

• If instead of

cnt = y+1; int y = cnt;

• We had written

cnt++;

• Answer: NO! • Would the result be any different?

  • Don’t depend on your intuition about atomicity

38

Question

• If you run a program with a race condition,

– ...and on the other threads/processes/etc that are– ...i.e., which JVM you’re running– No! It depends on the schedulerwill you always get an unexpected result?

running on the same CPU

• Race conditions are hard to find

39

Avoiding Interference:

Synchronization

public class Example extends Thread { public void run() {static Object lock = new Object();private static int cnt = 0; synchronized (lock)

cnt = y + 1;int y = cnt;

Lock

, for protecting

Acquires the shared state

(^) the lock;

Releases threadheld by anotherOnly succeeds if not

(^) the lock

40

Applying Synchronization

int (^) cnt =

(^) 0;

t1.run() { synchronized(lock) { int y

(^) = (^) cnt;

cnt =

(^) y (^) + 1;

}

t2.run() {} synchronized(lock) { int y

(^) = (^) cnt;

cnt =

(^) y (^) + 1;

}

}

cnt = 0

T1 acquires the lockShared state

41

Applying Synchronization

t1.run() { int cnt = 0; synchronized(lock) { cnt = y + 1;int y = cnt;

}

t2.run() {} synchronized(lock) { cnt = y + 1;int y = cnt;

}

}

cnt = 0

T1 reads cnt into yShared state

y = 0

42

Applying Synchronization

int (^) cnt =

(^) 0;

t1.run() { synchronized(lock) { int y

(^) = (^) cnt;

cnt =

(^) y (^) + 1;

}

t2.run() {} synchronized(lock) { int y

(^) = (^) cnt;

cnt =

(^) y (^) + 1;

}

}

cnt = 0

T1, so it blocksbecause it’s held byacquire the lock but failsT2 attempts toT1 is pre-empted.Shared state

y = 0

43

Applying Synchronization

t1.run() { int cnt = 0; synchronized(lock) { cnt = y + 1;int y = cnt;

}

t2.run() {} synchronized(lock) { cnt = y + 1;int y = cnt;

}

}

cnt = 1

to cntT1 runs, assigningShared state

y = 0

44

Applying Synchronization

int (^) cnt =

(^) 0;

t1.run() { synchronized(lock) { int y

(^) = (^) cnt;

cnt =

(^) y (^) + 1;

}

t2.run() {} synchronized(lock) { int y

(^) = (^) cnt;

cnt =

(^) y (^) + 1;

}

}

cnt = 1

and terminatesT1 releases the lockShared state

y = 0

49

Synchronized Statement

synchronized (obj) {

statements

• Obtains the lock on

obj

before executing

statements in block

• Releases the lock when the statement block

– Either normally, or due to a return, break, orcompletes

exception being thrown in the block

50

Synchronization not a Panacea

• Two threads can block on locks held by the

other; this is called

deadlock

Object

(^) A = (^) new Object();

Object

(^) B = (^) new Object();

T1.run() { synchronized (A)

(^) {

synchronized

(^) (B) {

}

}

}

T2.run() { synchronized (B)

(^) {

synchronized

(^) (A) {

}

}

}

51

Deadlock

• Quite possible to create code that deadlocks

  • Thread 1 holds lock on

A

  • Thread 2 holds lock on

B

  • Thread 1 is trying to acquire a lock on

B

  • Thread 2 is trying to acquire a lock on

A

  • Deadlock!

• Not easy to detect when deadlock has

– Other than by the fact that nothing is happeningoccurred

52

Deadlock: Wait graphs

A

T

Thread T1 holds lock A

B

T

acquire lock BThread T2 attempting to

Deadlock occurs when there is a cycle in the graph

53

Wait graph example

A

B T

T

T1 holds lock on

A

T2 holds lock on

B

T1 is trying to acquire a lock on

B

T2 is trying to acquire a lock on

A

54

Guidelines for Programming with

Threads

Synchronize access to shared data

  • Could cause deadlockDon’t hold multiple locks at a time
  • Reduces blocking waiting for locksHold a lock for as little time as possible
  • E.g., a method provided by someone else, especially ifdon’t understandWhile holding a lock, don’t call a method you you can’t be sure what it locks
  • Corollary: document which locks a method acquires