[go: up one dir, main page]

0% found this document useful (0 votes)
26 views35 pages

ICLP c1 Java1

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)
26 views35 pages

ICLP c1 Java1

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/ 35

Implementarea Concurent, ei în limbaje de

programare
Threads and shared memory — JAVA

Traian Florin S, erbănut, ă

FMI @ UNIBUC

1
Threads and shared memory 1

Concurrency primitives in Java

Thread synchronization mechanism

1
Operating Systems Concepts, 9th edition, by A. Silberschatz, P. B. Galvin, and
G. Gagne
2
Threads and shared memory
Threads

• Most modern applications are multithreaded


• Multiple tasks with the application can be implemented by
separate threads
• Update display
• Fetch data
• Spell checking
• Answer a network request
• Can simplify code, increase responsiveness

3
Example (Service Server Arhitecture)

4
Benefits

• Responsiveness
• may allow continued execution if part of process is blocked
• especially important for user interfaces
• Resource Sharing
• Scalability
• process can take advantage of multiprocessor architectures

5
Concurrency vs parallelism

Concurrent execution on single-core system:

Execut, ie concurentă în paralel pe un sistem multi-core:

6
Single vs Multithreaded process

7
Shared Memory

Benefits
• Efficiency: all threads have direct acecss to the memory
• Simplicity: Accessing shared memory using same model as for
sequential processes

Problems (the need for synchronization)


• Threads may be interruped at any time
• e.g., while performing a data-sensitive operation
• Concurrent access to shared data may result in data
inconsistency
• Maintaining data consistency requires mechanisms to ensure
the orderly execution of cooperating threads

8
Synchronization – Mutex (MUTual EXclusion)

• Special synchronization object

• Protects a “critical section” of code


• (sensitive to concurrent modifications)

• Two zones protected by same mutex cannot interrupt


each-other
Example - mutex m

First Thread Second Thread


do stuff do stuff
synchronized(m): synchronized(m):
output results output results
do other stuff do other stuff
9
Concurrency primitives in Java
Threads

Any executing thread is an instance of class Thread


Thread attributes
• ID: unique thread identifier
• getter: getId, cannot be set
• Name: thread name (String)
• getter/setter: getName, setName
• Priority: thread priority (integer between 1 and 10)
• getter/setter: getPriority, setPriority
• Larger number usually means greater execution priority
• changing priority does not guarantee actual priority
• State: Thread state
• getter: getState, cannot be set

10
Thread state

public static enum Thread.State extends Enum<Thread.State>

• NEW: thread which has not yet started.


• RUNNABLE: thread which can execute/is executing
• BLOCKED: blocked, waiting for a monitor lock
• WAITING: waiting for a signal from another thread
• TIMED_WAITING: waiting thread with a specified waiting time.
• TERMINATED: thread which has finished executing.

A thread can only be in one of these states at any given time.

11
Thread life-cycle (source: HowToDoInJava.com)

Thread states and transitions between them


Figure 1: Thread states and transitions between them

12
Thread creation

Direct
• by deriving Thread class
• by implementing the Runable interface

Abstract
• Using the Executors class

13
Thread creation using Runnable

Standard
public class HelloRunnable implements Runnable {
public void run() { System.out.println("Hello thread!"); }
public static void main(String args[]) {
Thread t = new Thread (new HelloRunnable());
t.start();
} }

Java 8 (funct, ii anonime)


public class HelloThread {
public static void main(String args[]) {
new Thread( () -> System.out.println("Hello thread!")
).start();
} }

14
Definirea unui thread ca subclasa a clasei Thread

public class HelloThread extends Thread {

public void run() {


System.out.println("Hello thread!");
}

public static void main(String args[]) {


new HelloThread().start();
}
}

15
public class Thread implements Runnable

• Dynamic methods (called on a Thread object)

start() A new execution thread is created and the JVM


invokes the run() method

join() waits for the given thread to finish execution

interrupt() asks the given thread to interrupt its execution

boolean isAlive() tests whether the thread is alive

• Static methods (applying to the current thread)

yield() current thread is willing to yield the processor

sleep(long milis) current threads sleeps for given time

Thread currentThread() Returns a reference to the


currently executing thread 16
JVM threads (source: docs.oracle.com)

When a Java Virtual Machine starts up, there is usually a single


non-daemon thread2 , which typically calls the method named main
of some designated class.

The Java Virtual Machine continues to execute threads until either:

• The exit method of class Runtime has been called and the
security manager permits the exit operation to take place.
• All threads that are not daemon threads have died, either
• by returning from the call to the run method or
• by throwing an exception that propagates beyond the run
method.
2
Daemon thread: low priority thread servicing user threads (e.g. garbage
collector thread)
17
Thread.sleep() and InterruptedException

sleep() throws an exception if the thread is interruped while still


sleeping.

public class SleepyMessages {


public static void main(String args[])
throws InterruptedException {
String importantInfo[] =
{ "This", "is", "very", "important"};

for (int i = 0; i < importantInfo.length; i++) {


Thread.sleep(4000);//Pause for 4 seconds
System.out.println(importantInfo[i]);
}
}
}

18
sleep, handling the InterruptedException

public class MessageLoop implements Runnable {


public void run() {
String importantInfo[] =
{"This", "is", "very", "important"};
try {
for (int i = 0; i < importantInfo.length; i++) {
Thread.sleep(4000);//Pause for 4 seconds
threadMessage(importantInfo[i]);
}
} catch (InterruptedException e) {
threadMessage("I wasn't done!");
}
}

19
currentThread, getName

public static void threadMessage(String message) {


String threadName = Thread.currentThread().getName();
System.out.format("%s: %s%n", threadName, message);
}

public static void main(String args[])


throws InterruptedException {
threadMessage("Starting MessageLoop thread");
Thread t = new Thread(new MessageLoop());
t.start();
threadMessage("Waiting for MessageLoop thread to finish");
t.join();
threadMessage("Finally!");
}
}

20
isAlive, join with timeout, and interrupt

public class MessageLoopInterrupted {


public static void main(String args[])
throws InterruptedException {
long patience = 1000 * 10;
long startTime = System.currentTimeMillis();
threadMessage("Starting MessageLoop thread");
Thread t = new Thread(new MessageLoop()); t.start();
threadMessage("Waiting for MessageLoop thread to finish");
while (t.isAlive()) {
threadMessage("Still waiting..."); t.join(2000);
if ((System.currentTimeMillis() - startTime
> patience) && t.isAlive()) {
MessageLoop.threadMessage("Tired of waiting!");
t.interrupt(); t.join();
} }
MessageLoop.threadMessage("Finally!"); } }

21
Rulare MessageLoopInterrupted

main: Starting MessageLoop thread


main: Waiting for MessageLoop thread to finish
main: Still waiting...
main: Still waiting...
Thread-0: This
main: Still waiting...
main: Still waiting...
Thread-0: is
main: Still waiting...
main: Tired of waiting!
Thread-0: I wasn’t done!
main: Finally!

22
ThreadLocal: variables local to the thread

public class ThreadLocalId implements Runnable {


private ThreadLocal<Long> threadLocal = new ThreadLocal<>();

public void run() {


threadLocal.set(Thread.currentThread().getId());
System.out.format("Name: %s Id: %d%n",
Thread.currentThread().getName(), threadLocal.get());
}

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


ThreadLocalId sharedRunnable = new ThreadLocalId();
Thread thread1 = new Thread(sharedRunnable);
Thread thread2 = new Thread(sharedRunnable);
thread1.start(); thread2.start();
thread1.join(); thread2.join();
}
}
23
Thread interference

public class Interference {


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

24
Thread interference

public class Interference {


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

++ and -- are not atomic


c = 2343

24
Thread synchronization mechanism
Intrinsic locks

• Every object has an intrinsic lock associated with it

• A thread needing to access an object’s fields should


• acquire the objects intrinsic lock
• access/alter the object’s data
• release the intrinsic lock

• No thread can acquire a lock while another one holds it


• a thread attempting to do so will block in the acquire phase

25
Thread syncronization
Synchronized methods
private synchronized void syncMethod () {
//method body
}

Synchronized code
synchronized (object reference){
// code
}

Synchonized methods are synchronizing the body using this


private void syncMethod () {
synchronized (this){
//method body
}
}

26
When calling a synchronized method

Non-static synchronized methods


• The intrinsic lock of the object is acquired
• The method is executed
• The intrinsic lock of the object is released
• no other non-static, syncronized methods can be called
simultaneously on the same object

Static synchronized methods


• Static methods use the Class object for that class
• No other static synchronized methods belonging to the same
class can be called simultaneously

27
Solving interference by synchronization (on statements)

public class NonInterference {


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

28
Solving interference through synchronized methods

public class SynchronizedMethod implements Runnable {


private int c = 0;
public static void main(String[] args)
throws InterruptedException {
SynchronizedMethod sm = new SynchronizedMethod();
Thread t1 = new Thread(sm); Thread t2 = new Thread(sm);
t1.start(); t2.start(); t1.join(); t2.join();
System.out.println("c = " + sm.c);
}

@Override public void run() {


for (int x = 0; x < 5000; ++x) incrementC();
}

synchronized void incrementC() { c++; }


}

29
Lock properties

• Only one thread can hold a given lock at any given time

• A thread holds the intrinsic lock of an object if either


• it executes a synchronized method of the object
• it executes a block synchronized by the object
• if the object’s type is Class, and the thead executes a
static synchronized method

30
Warnings

• Access to the non-synchronized methods is not blocked


• Static and non-static synchronized methods do not mutually
exclude each-other
• A thread can re-aquire a lock it is already holding (reentrant
synchronization)
• Thread.sleep() does not release the locks
• ob.wait() releases the intrinsic lock of ob held by the thread

31

You might also like