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

ICLP c3 Java3

Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
7 views

ICLP c3 Java3

Copyright
© © All Rights Reserved
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