Въведение в java.util.concurrent

Preview:

DESCRIPTION

Въведение в java.util.concurrent. Михаил Стойнов & Красимир Семерджиев. Agenda. Hardware evolution - free lunch is over Java concurrency before Java SE 5 Atomic operations Java.util.concurrent overview Java SE5 vs. Java SE6. Hardware evolution. - PowerPoint PPT Presentation

Citation preview

Михаил Стойнов &

Красимир Семерджиев

Hardware evolution - free lunch is over Java concurrency before Java SE 5 Atomic operations Java.util.concurrent overview Java SE5 vs. Java SE6

?!?!?

Moore’s law for CPU clock speed is over

Intel talks about 100x core CPU

Next major revolution in software - concurrency

Majority of software is not ready for that

“There ain’t no such thing as a free lunch.” —R. A. Heinlein,

Availability – faster response time, maximize throughput, access DBs/backends

GUIs– autonomous objects, animation, concurrent events

Parallelism – utilizing CPUs, overlapping I/O, multiple clients

Protection – isolating different activities,

Hard to implement!

Higher resource usage

Need to start decomposing tasks

Deal with safety and isolation

System(VM) = Objects + Activities(Threads) Activities touch/change objects’ state Every called method should eventually

execute as soon as possible Liveness and safety not enforced by

compilers

Java Virtual Machine

Every object has a lock Every Class has a lock (being an Object) Acquiring locks works through

“synchronized” blocks/methods Can “temporarily release” the lock by

calling wait() or wait(ms) Can wake up waiting threads by calling

notify() or notifyAll() Synchronized blocks control atomicity

Object

method

lock

method

method

Objects represent a state and procedures over it

Every Thread represents the state of a single activity touching different objects

Synchronized block ensures thread-local cache flush/reload

Volatile keyword ensures per-variable cache flush/reload

Stateless objects – comprise mainly of methods

Immutable objects – state never changes after creation

Atomic objects – legal-to-legal state changes only

Locking – exclusive access on state change

Make sure that a user always sees a legal state (never sees a temporary state)

Make sure that you have only legal->legal transitions

Java doesn’t guarantee fairness Locks are reentrant Wrong order of acquiring nested monitors

leads to deadlock Once deadlocked – threads will hang forever On wait(ms) you dunno whether it was a

notify() call or timeout that happened Thread scheduling provides no guarantees Lock contention is a scalability blocker

CAS stands for Compare-and-Swap Atomic instruction at CPU level (cmpxchg,

load and reserve, store conditional, etc.). Since Java SE 5 – adopted in Java to

allowing concurrent structures to be implemented. Old

value

=?

Ignore Set it

Setting a reference to an existing object is an atomic operation

Object construction is not an atomic operation!

Too low level – hard to implement high level structures (like latch, rendezvous and barrier)

Can’t pass a lock between threads Can’t attach a lock to an Object while no

thread is working with it

Lock contention – too many threads/CPUs Multiple-request data changes Fine-grained locking Keeping a lock without wasting a thread

The java.util.concurrent package aims to do for concurrency what java.util.Collections did for data structures. It makes◦ Some problems go away◦ Some problems trivial to solve by everyone◦ Some problems easier to solve by concurrent programmers◦ Some problems possible to solve by experts

Whenever you are about to use... Object.wait, notify, notifyAll, synchronized, new

Thread(); Check first if there is a class that ...

◦ automates what you are trying to do, or ◦ would be a simpler starting point for your own solution

java.util.concurrent is based on over 3 years experience with edu.oswego.cs.dl.util.concurrent

Many refactorings and functionality improvements

Additional native/JVM support ◦ Timing, atomics, built-in monitor extensions

Executors, Thread pools, and Futures Queues and blocking queues Timing Locks and Conditions Synchronizers: Semaphores, Barriers, etc Atomic variables Miscellany

Flexibility at expense of verbositylock.lock();

try {

action();

}

finally {

lock.unlock();

}

Overcomes limitations of synchronized◦ Doesn’t force block structured locking/unlocking◦ Allow interruptible lock acquisition and “try lock”◦ Can define customized implementations◦ Fair/Unfair

interface Lock {

void lock();

void lockInterruptibly() throws IE;

boolean trylock();

boolean trylock(long timeout,

TimeUnit unit)throws IE;

void unlock();

Condition newCondition();

}

Concrete ReentrantLock implementation◦ Fast, scalable with synchronized block semantics,

and additional query methods◦ Also FairReentrantLock subclass with slower but

more predictable first-in-first-out arbitration

class ParticleUsingLock { private int x, y; private final Random rng = new Random();private final Lock lock = new ReentrantLock(); public void move() throws InterruptedException { lock.lockInterruptibly(); // allow cancellation try { x += rng.nextInt(3) - 1; y += rng.nextInt(3) – 1; } finally { lock.unlock(); } } public void draw(Graphics g) { int lx, ly; lock.lock(); // no interrupts – AWT Event Thread try { lx = x; ly = y; } finally { lock.unlock(); } g.drawRect(lx, ly, 10, 10); } }

interface ReadWriteLock { Lock readLock(); Lock writeLock();}

A pair of locks for enforcing multiple-reader, single-writer access◦ Each used in the same way as ordinary locks

Concrete ReentrantReadWriteLock◦ Almost always the best choice for apps◦ Each lock acts like a reentrant lock

Remember Lock.newCondition(); ? Condition factors out the Object monitor

methods (wait, notify and notifyAll)◦ into distinct objects to give the effect of having

multiple wait-sets per object◦ can combine them with the use of arbitrary Lock

implementations. Where a Lock replaces the use of synchronized methods and statements, a Condition replaces the use of the Object monitor methods.

interface Condition {

void await() throws IE;

void awaitUninterruptibly();

long awaitNanos(long nanos) throws IE;

boolean awaitUntil(Date deadline) throws IE;

void signal();

void signalAll();

}

Allows more than one wait condition per object◦ Even for built-in locks, via Locks utility class

Allows much simpler implementation of some classic concurrent designs

Example

A small collection of small classes that:◦ Provide good solutions to common special-

purpose synchronization problems◦ Provide better ways of thinking about designs

But worse ways when they don't naturally apply!

◦ Can be tricky or tedious to write yourself Semaphore CountDownLatch CyclicBarrier

Semaphores can be seen as permit holders◦ Create with initial number of permits ◦ acquire takes a permit, waiting if necessary◦ release adds a permit◦ But no actual permits change hands.◦ Semaphore just maintains the current count.

Can use for both “locking” and “synchronizing”◦ With initial permits=1, can serve as a lock◦ Useful in buffers, resource controllers◦ Use in designs prone to missed signals ◦ Semaphores “remember” past signals

A synchronization aid that allows one or more threads to wait until a set of operations being performed in other threads completes.

A CountDownLatch is initialized with a given count

The await methods block until the current count reaches zero due to invocations of the countDown method, after which all waiting threads are released and any subsequent invocations of await return immediately. This is a one-shot phenomenon -- the count cannot be reset.

class Driver { // ... void main(int N) throws InterruptedException { final CountDownLatch startSignal = new CountDownLatch(1); final CountDownLatch doneSignal = new CountDownLatch(N); for (int i = 0; i < N; ++i) // Make threads new Thread() { public void run() { try { startSignal.wait(); doWork(); doneSignal.countDown(); } catch(InterruptedException ie) {} }}.start(); initialize(); startSignal.countDown(); // Let all threads proceed doSomethingElse(); doneSignal.await(); // Wait for all to complete cleanup(); }}

Example

j.u.c.atomic contains classes representing scalars supporting "CAS“

boolean compareAndSet(expectedV, newV)◦ Atomically set to newV if holding expectedV◦ Always used in a loop

Essential for writing efficient code on MPs◦ Nonblocking data structures, optimistic algorithms,

reducing overhead and contention when updates center on a single field

JVMs use best construct available on platform◦ Compare-and-swap, Load-linked/Store-conditional, Locks

j.u.c.a also supplies reflection-based classes that allow CAS on given volatile fields of other classes

class Random { // snippets private AtomicLong seed; Random(long s) { seed = new AtomicLong(s); } long next(){ for(;;) { long s = seed.get(); long nexts = s * ... + ...; if (seed.compareAndSet(s,nexts) return s; } } }

Faster and less contention in programs with a single Random accessed by many threads

Let’s see java.util.Random

There’s also an AtomicReference class Why not use that to create a non-blocking

stack? The idea is the same:

◦ The push() method observes the current top node◦ constructs a new node to be pushed on the stack◦ if the topmost node has not changed since

the initial observation, installs the new node◦ If the CAS fails, it means that another thread

has modified the stack, so the process starts again

Example

The Segments◦ The maps is split into segments, only they lock

The root link Retries before resorting to locking – size()

Basic debugging support is added (in jconsole and thread dumps) to detect deadlocks based on java.util.concurrent structures

Double-ended deques added

Looking at thread dump (Ctrl+Break)◦ Locked monitors are noted◦ Monitors to wait for are shown◦ Owned synchronizers are listed◦ Java-level (synchronized) deadlocks are auto

detected

These slides are for educational purpose only

In most of the cases synchronized blocks are sufficient!

Synchronized blocks modes is intentionally kept simple

java.util.concurrent is hard to debug and needlessly complex for simple scenarios!

Do not use java.util.concurrent except if you really HAVE to!

Three short articles from Brian Goetz:http://www-128.ibm.com/developerworks/java/library/j-jtp04186/http://www-128.ibm.com/developerworks/java/library/j-jtp11234/http://www-128.ibm.com/developerworks/java/library/j-jtp10264/

For further questions:Михаил Стойновmihail@stoynov.commihail.stoynov.com/blogКрасимир Семерджиевkrasimir.semerdzhiev@sap.comBulgarian Java Users Groupjava-bg.orggroups.google.com/group/bg-jug

Recommended