review (and some new information!) · in java, it is not guaranteed that thread 1 sees...

14
Review (and some new information!)

Upload: others

Post on 18-Jul-2020

3 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Review (and some new information!) · In Java, it is not guaranteed that thread 1 sees modifications made by thread 2 unless thread 1 and thread 2 synchronize (for example with a

Review

(and some new information!)

Page 2: Review (and some new information!) · In Java, it is not guaranteed that thread 1 sees modifications made by thread 2 unless thread 1 and thread 2 synchronize (for example with a

Creating threads

▪ We saw last week that all programs have one thread (created by the

operating system when the program is started) and that you can create

more threads:

public static void main(String[] args) {

Thread t = new Thread(() -> {System.out.println(“Hello world"); String name = "This is "+Thread.currentThread().getName();System.out.println(name);

}, "My new thread");

t.start();

int name = "This is "+Thread.currentThread().getName();System.out.println(name);

}

Main thread

My new thread

Page 3: Review (and some new information!) · In Java, it is not guaranteed that thread 1 sees modifications made by thread 2 unless thread 1 and thread 2 synchronize (for example with a

Futures and threadpools

▪ We also saw that Futures and threadpools are very useful if you work

with threads that produce a result:

public static int calculate(int a, int b) {int sum = 0;for(int i=a;i<=b;i++) {

sum += i;}return sum;

}

public static void main(String[] args)throws ExecutionException, InterruptedException {

ExecutorService executor = Executors.newFixedThreadPool(2);

Future<Integer> f1 = executor.submit(()-> calculate(1,500));Future<Integer> f2 = executor.submit(()-> calculate(501,1000));

int sum = f1.get() + f2.get();executor.shutdown();

}

Future.get() waits until a

thread has finished the

calculation for the future.

We give the

threadpool two

tasks to do.

Page 4: Review (and some new information!) · In Java, it is not guaranteed that thread 1 sees modifications made by thread 2 unless thread 1 and thread 2 synchronize (for example with a

Race conditions

▪ We saw that unexpected things can happen if a thread works with a

variable or object that is modified by another thread at the same time.

▪ Source code:

▪ Possible execution:

Thread 1:

Element newElement=new Element(3);newElement.next=head;head=newElement;

Thread 2:

Element newElement=new Element(4);newElement.next=head;head=newElement;

Thread 2

Element thread2_newElement=new Element(4);

thread2_newElement.next=head;head=thread2_newElement;

Thread 1 overwrites the

change made by thread 2!

Thread 1

Element thread1_newElement=new Element(3);

thread1_newElement.next=head;

head=thread1_newElement;

Page 5: Review (and some new information!) · In Java, it is not guaranteed that thread 1 sees modifications made by thread 2 unless thread 1 and thread 2 synchronize (for example with a

Race conditions (2)

▪ Be careful: Race conditions can even happen in a single line of code

▪ A line like

i = i + 1; (“Bad example 1” from last week)

consists of three low-level instructions for your computer:

1. Read the value of variable 𝑖

2. Add 1 to that value

3. Store the result in variable 𝑖

▪ With two threads, the following can happen:

Read the value of variable 𝑖

Add 1 to that value

Store the result in variable 𝑖

Read the value of variable 𝑖Add 1 to that value

Store the result in variable 𝑖

Thread 1 Thread 2

Thread 1 overwrites the

change made by thread 2!

Page 6: Review (and some new information!) · In Java, it is not guaranteed that thread 1 sees modifications made by thread 2 unless thread 1 and thread 2 synchronize (for example with a

Synchronization with monitors

▪ Monitors can be used to protect a critical section of the code, such that

only one thread executes the critical section at a time:

synchronized(someObject) {.........

}

Thread X

Thread X becomes

the owner of the

monitor and can

enter the critical

section Thread Y Thread Z

The other threads

must wait until thread

X leaves the block

When Thread X leaves

the block, one of the

two waiting threads Y or

Z can enter

The synchronized

statement always

needs an object

Page 7: Review (and some new information!) · In Java, it is not guaranteed that thread 1 sees modifications made by thread 2 unless thread 1 and thread 2 synchronize (for example with a

Where to put the synchronized statement

▪ Different places possible for a synchronized statement

▪ It can be before you call a method:

▪ Or inside a method that you call:

▪ Often, the entire method is synchronized:

synchronized(someObject) {list.add(3);

}

void add(int value) {Element newElement=new Element(value);synchronized(someObject) {

newElement.next=head;head=newElement;

}}

synchronized void add(int value) {Element newElement=new Element(value);newElement.next=head;head=newElement;

}

Page 8: Review (and some new information!) · In Java, it is not guaranteed that thread 1 sees modifications made by thread 2 unless thread 1 and thread 2 synchronize (for example with a

Visibility

▪ The Synchronized statement also does something else: It guarantees the

visibility of data modifications to threads

▪ Incorrect example:

▪ Will thread 1 ever terminate?

▪ We don’t know! In Java, it is not guaranteed that thread 1 sees

modifications made by thread 2 unless thread 1 and thread 2 synchronize

(for example with a synchronized statement)

someObject.b=true;...while(someObject.b) {

...}

Thread 2

someObject.b=false;

Thread 1

Page 9: Review (and some new information!) · In Java, it is not guaranteed that thread 1 sees modifications made by thread 2 unless thread 1 and thread 2 synchronize (for example with a

Visibility (2)

▪ Using a synchronized statement is one way to ensure the visibility of

modifications

▪ It is also possible to declare a class member as volatile:

▪ When a class member is volatile, Java guarantees that a thread reading

the variable

will see all previous modifications by other threads

class SomeClass {volatile boolean b;

}

Example: while(someObject.b) { ...

Example: someObject.b=false;

Page 10: Review (and some new information!) · In Java, it is not guaranteed that thread 1 sees modifications made by thread 2 unless thread 1 and thread 2 synchronize (for example with a

▪ How can a computer execute multiple threads at the same time? Why

don’t threads see modifications made by other threads?

• LINFO1252: Systèmes informatiques

• LINGI2241: Computer architecture and performance

• LINGI2355: Multicore programming

▪ How do you design algorithms and programs with threads? How can

you prove that a program with multiple threads works correctly?

• LINFO1104: Paradigmes de programmation et concurrence

• LINGI2143: Concurrent systems : models and analysis

• LSINF2345: Languages and algorithms for distributed Applications

Page 11: Review (and some new information!) · In Java, it is not guaranteed that thread 1 sees modifications made by thread 2 unless thread 1 and thread 2 synchronize (for example with a

Classes in java.util.*

▪ Most data structures in java.util.* are not thread-safe: race conditions

can happen!

• ArrayList, LinkedList, HashSet, PriorityQueue, HashMap,...

▪ If you want to work with these classes from multiple threads, you have

to use synchronized-statements in your code

▪ But there already a lot of helper classes and methods that you can use:

// creates a thread-safe map

Map m = Collections.synchronizedMap(new HashMap(...));

// creates a thread-safe list

List list = Collections.synchronizedList(new LinkedList(...));

▪ There are many other methods to create thread-safe sets,

queues, etc.

Page 12: Review (and some new information!) · In Java, it is not guaranteed that thread 1 sees modifications made by thread 2 unless thread 1 and thread 2 synchronize (for example with a

How doesCollections.synchronizedList work?▪ The method synchronizedList in

List list = Collections.synchronizedList(new LinkedList(...));

returns an object of type SynchronizedList

▪ SynchronizedList is a wrapper class (a design pattern!). It doesn’t contain

any data. It just wraps thread-safe methods “around” a normal list object:

class SynchronizedList {final List list;final Object mutex = new Object();

SynchronizedList(List list) {this.list = list;

}

public void add(int index, E element) {synchronized (mutex) {

list.add(index, element);}

}...

}

mutex = “Mutual

exclusion”

Page 13: Review (and some new information!) · In Java, it is not guaranteed that thread 1 sees modifications made by thread 2 unless thread 1 and thread 2 synchronize (for example with a

// Code for T2:while(true) {

Picture currentPicture;synchronized(someObject) {

while(picture==null) {try {

someObject.wait();}catch(InterruptedException e) { throw new RuntimeException(“...", e); }

}currentPicture=picture;picture=null;someObject.notify();

}

CompressedPicture p=compress(currentPicture);p.writeToFile();

}

wait() and notify()

// Code for T1while(true) {

Picture currentPicture = takePhoto();synchronized(someObject) {

while(picture!=null) {try {

someObject.wait();}catch(InterruptedException e) { throw new RuntimeException(“...", e); }

}picture = currentPicture;someObject.notify();

}}

Wait until

picture==null

Notify other waiting

threads that picture

is now !=null

Wait until

picture!=null

Notify other waiting

threads that picture is

now ==null

Page 14: Review (and some new information!) · In Java, it is not guaranteed that thread 1 sees modifications made by thread 2 unless thread 1 and thread 2 synchronize (for example with a

Waiting with timeout

▪ Sometimes, you want to limit the time to wait (BoundedBuffer exercise

on inginious):

▪ The thread stops waiting if:

• another thread calls notify() or notifyAll()

• the time is over

• the waiting is interrupted (InterruptedException)

▪ Don’t forget to test after waiting if the condition you were waiting for is

satisfied.

someObject.wait(2000); // wait maximum 2000ms