0% found this document useful (0 votes)
8 views

ICLP c3 Java3

Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
8 views

ICLP c3 Java3

Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 32

Implementarea Concurent, ei în limbaje de

programare
JAVA 3

Traian Florin S, erbănut, ă

FMI @ UNIBUC

1
Synchronization using class Lock

Readers-Writers Model

Executor, ExecutorService, Executors

Sequential consistency

2
Synchronization using class Lock
Lock vs synchronized

synchronized (ob) { ... }


• Uses the intrinsic lock of the object
• Forces a structured approach to synchronization:
• intrinsic lock automatically released upon exiting the block

Objects of classes implementing the Lock interface


• Manage their own locks
• more flexible
• threads can access locks in any order;
• making sure the lock is released falls on the programmer
Lock l = ...
l.lock();
try {
...
} finally { l.unlock(); }

3
Avoiding interference using Lock

public class NonInterference {


static int c = 0;
public static void main(String[] args)
throws InterruptedException {
Lock cLock = new ReentrantLock();
Thread myThread = new Thread(() -> {
for (int x = 0; x < 5000; ++x)
{cLock.lock(); try {c++;} finally {cLock.unlock();}}
});
myThread.start();
for (int x = 0; x < 5000; ++x)
{cLock.lock(); try {c--;} finally {cLock.unlock();}}
myThread.join();
System.out.println("c = " + c);
}
}

4
interface Lock

void lock() Acquires lock associated to object; may block

void unlock() Releases lock associated to object; not blocking

void lockInterruptibly() Acquires associated lock - if the


thread is not interrupted; may block

boolean tryLock() Acquires the lock if available when invoked;


not blocking

boolean tryLock(long time, TimeUnit unit) Acquires the


lock if it becomes available within the given time

Condition newCondition() Creates a new Condition variable


corresponding to the current Lock instance.

5
interface Condition

• Implements methods similar to wait and notify for Locks

await(), await(long time, TimeUnit unit) Current


threads waits for a signal on this condition

signal(), signalAll() one/all thread(s) waiting for this


condition is/are signaled to wake.

• Similarly to Object, conditions are linked to a Lock object


• lock must be acquired before calling wait()

• Multiple conditions can coexist for the same lock

6
Better Producer-Consumer Solution using Lock and Condition
(I)

public class Cell<T> implements DropBox<T> {


private T cell = null;
private boolean open = true;
private Lock cellLock;
private Condition putCond;
private Condition getCond;

public Cell() {
cellLock = new ReentrantLock();
putCond = cellLock.newCondition();
getCond = cellLock.newCondition();
}

7
Better Producer-Consumer Solution using Lock and Condition
(put)

@Override public boolean put(T message)


throws InterruptedException {
cellLock.lock();
try {
while (open && cell != null) putCond.await();
if (!open) return false;
cell = message;
getCond.signal();
return true;
} finally {
cellLock.unlock();
}
}

8
Better Producer-Consumer Solution using Lock and Condition
(take)

@Override public Optional<T> take()


throws InterruptedException {
cellLock.lock();
try {
while (open && cell == null) getCond.await();
if (open) putCond.signal();
T message = cell;
cell = null;
return Optional.ofNullable(message);
} finally {
cellLock.unlock();
}
}

9
Better Producer-Consumer Solution using Lock and Condition
(close)

@Override public void close() {


cellLock.lock();
try {
open = false;
putCond.signalAll();
getCond.signalAll();
} finally {
cellLock.unlock();
}
}
}

Notes
• using different conditions for put and take
• Advantage: no need to wake all threads each time something
changes
10
Readers-Writers Model
Readers-Writers Interaction Model

• Multiple threads need concurrent access to the same resource


• Some threads write (writers), others only read (readers).
• The resource can be read simultaneously by multiple readers
• The resource cannot be written simultaneously
• The resource cannot be simultaneously read and written
Expressed in Java through the ReadWriteLock interface
readLock() yields the lock for readers
writeLock() yields the lock for writers

11
Addressing non-interference using ReadWriteLock (reader
thread)

public class NonInterferenceRW {


static int c;
public static void main(String[] args)
throws InterruptedException {
final ReadWriteLock lock = new ReentrantReadWriteLock();

Runnable reader = () -> {


lock.readLock().lock();
try {
System.out.println(Thread.currentThread().getName()
+ " counter: " + c);
} finally { lock.readLock().unlock(); }
};

12
Addressing non-interference using ReadWriteLock (writer
threads)

Thread incThread = new Thread(() -> {


for (int x = 0; x < 5000; ++x) {
lock.writeLock().lock(); try {
for (int i = 0; i < 5; i++)
{ c++; Thread.yield(); }
} finally { lock.writeLock().unlock(); }
}});

Thread decThread = new Thread(() -> {


for (int x = 0; x < 5000; ++x) {
lock.writeLock().lock(); try {
for (int i = 0; i < 5; i++)
{ c--; Thread.yield(); }
} finally { lock.writeLock().unlock(); }
}});

13
Addressing non-interference using ReadWriteLock (main setup)

incThread.start();
decThread.start();
ExecutorService executorService =
Executors.newFixedThreadPool(2);
for (int i = 0; i < 100; i++)
executorService.execute(reader);
executorService.shutdown();
while (!executorService.isTerminated()) {
executorService.awaitTermination(1, TimeUnit.SECONDS);
}
incThread.join();
decThread.join();
System.out.println("c = " + c);
}
}

14
Executor, ExecutorService,
Executors
Executor and ExecutorService interfaces

Executor is an abstraction over Thread


void execute(Runnable task) Executes a task; whether
blocking or non-blocking, implementation decides

ExecutorService enhances the Executor functionalities


• . . . with ways to control execution
for (int i = 0; i < 100; i++) executorService.execute(reader);
executorService.shutdown();
while (!executorService.isTerminated()) {
executorService.awaitTermination(1, TimeUnit.SECONDS);
}

• . . . with ways to wait for results (next section)

15
class Executors

Provides static methods for creating ExecutorServices

static ExecutorService newCachedThreadPool() creates a


pool of threads to execute tasks. Reuses ended
threads. Uses a queue for tasks.

static ExecutorService newFixedThreadPool(int nThreads)


creates pool of nThreads threads to execute tasks.
Uses a (blocking) queue for scheduling tasks.

static ExecutorService newSingleThreadExecutor()


creates a single-threaded pool for executing tasks.
Uses a queue for tasks.

16
Asynchronous functions in Java: Callable, Future

Callable<T>
• Abstraction for actions (concurrent or not) returning a result
• think of it as a Runnable returning a value.
Callable<Integer> giveMeFive = () -> 5;

Future<T>
The promise of an Executor to deliver the result of a Callable
T get() Obtains the result promised by the Future. May block
waiting for the action to conclude

The submit method from ExecutorService


Future<T> submit(Callable<T> task) Schedules a task for
execution, returning a promise to deliver its result

17
Future

• ExecutorService.submit(task) returns a Future


• does not block; calling thread continues executing tasks
• even for a single-threaded Executor
• Result promised Future is obtained using get()
• get() blocks calling thread until result becomes available.
• if the thread executing the Callable is interrupted, throws
• isDone() called for a Future tells whether result is available.

18
Future example using isDone

public class FutureExample {


public static void main(String[] args) throws Exception {
ExecutorService executor =
Executors.newSingleThreadExecutor();
Future<Integer> future = executor.submit(() -> {
int time = ThreadLocalRandom.current().nextInt(1000, 5000);
Thread.sleep(time); return time;
});
while (!future.isDone())
{ System.out.println("Task not done ...");
Thread.sleep(500); }
System.out.println("Task duration: " + future.get());
executor.shutdown();
}
}

19
ExecutorService: invokeAll and invokeAny

List<Future<T>>

invokeAll(Collection<? extends Callable<T>> tasks)


Schedules all tasks for execution

• returns a Future for each task


• Blocks untill all tasks are done.

T invokeAny(Collection<? extends Callable<T>> tasks)


Schedules all taks for execution

• returns one of the results


• the other tasks are canceled

20
invokeAll example

Optional<To> mapReduce(Collection<From> c,
Function<From, To> map,
BinaryOperator<To> reduce)
throws Exception {
return
executor.invokeAll(
c.stream()
.map( e -> ((Callable<To>) () -> map.apply(e)) )
.collect(Collectors.toList())
).stream()
.map(InvokeAllExample::get)
.reduce(reduce);
}

21
invokeAny example

• Allows concurrent execution of multiple tasks


• Choses the task finishing first
• Useful when having more methods for solving the same problem

int search(Integer key)


throws ExecutionException, InterruptedException {
return executor.invokeAny(Arrays.asList(
() -> search1(key),
() -> search2(key),
() -> search3(key)));
}

22
Sequential consistency
Concurrent objects and serial specification

Concurrent objects
Shared entities upon which a thread can perform certain operations

Serial specification
The valid behavior of a concurrent object (in isolation)
• we only observe the operations performed on that object

23
Concurrent object example: shared memory location

Operations
read Reading the value from the memory location
write Writing a value into the memory location

Serial specification
Every read operation yields the value written by the latest write.

24
Concurent object example: mutex (lock)

Operations
lock acquires the lock
unlock releases the lock

Serial specification
• #lock - #unlock is either 0 or 1 for all prefixes
• sequence of lock unlock pairs
• last unlock can miss
• Consecutive lock - unlock operations belong to same thread

25
Formalizing sequential consistency [Attiya&Welch, 1994]
Legal execution
• Any concurrent object satisfies its serial specification
• When restricting the execution to that object alone.

Execution reordering
A permutation of the events in the original execution such that its
restriction to each thread is the same as in the original execution

Sequential consistent execution


An execution admitting a legal reordering

Guarantees offered by sequential consistency


• Execution happens as if it were legal
• Programmer can assume each concurrent object behaves
according to its serial specification
26
The Java memory model

• Sequential consistency <= program is correctly synchronized

Correctly synchronized no data-races

Data-race conflictual access not ordered by happens-before

concurrent access to same location, one is write


The Happens-before relation hb(x,y)
Thread order x before y within the same thread => hb(x,y)
Synchronization x synchronizes with subsequent action y =>
hb(x,y)
Transitivity hb(x,y) and hb(y,z) => hb(x,z)
Constructor-Finalizer If x is the end of a constructor and y is the
call to finalize for that object => hb(x,y)

27
Synchronization order

• unlock synchronizes with subsequent locks on same monitor


• write of volatile v synchronizes with subsequent reads of v
• Thread start synchronizes with first operation in that thread
• Final operation in thread synchronizes with any operation
detecting that the thread has ended

28

You might also like