Download presentation
Presentation is loading. Please wait.
Published byHarriet Horton Modified over 9 years ago
1
2015/5/8Institute of Computer Software Nanjing University Concurrent Objects
2
2015/5/8Institute of Computer Software Nanjing University Concurrent Object-Oriented programming Basics Concurrency and OOP The Java concurrency model Semaphores and reader/writer in Java (New concurrency support in Java 1.5)
3
2015/5/8Institute of Computer Software Nanjing University Basics Slides from ETH (by P. Eugster) Introduciton and Motivation for Concurrent Programming Introduciton and Motivation for Concurrent Programming Classic Approaches to Concurrent Programming
4
2015/5/8Institute of Computer Software Nanjing University 复习: What is “Concurrency”? Edsger Dijkstra "Concurrency occurs when two or more execution flows are able to run simultaneously." “Concurrency = absence of causal order”
5
2015/5/8Institute of Computer Software Nanjing University 复习:为何进行并发程序设计 Motivation and Introduction
6
2015/5/8Institute of Computer Software Nanjing University 复习:经典并发程序设计技术 Classical Approaches
7
2015/5/8Institute of Computer Software Nanjing University Concurrence VS. Object-orientation Robin Milner said [Matsuoka 1993]: "I can't understand why objects [of O-O languages] are not concurrent in the first place".
8
2015/5/8Institute of Computer Software Nanjing University
9
2015/5/8Institute of Computer Software Nanjing University
10
2015/5/8Institute of Computer Software Nanjing University Concurrent OOP 如何结合并发程序设计的 Task/Thread 概念和 面向对象程序设计的 Object 概念? 完全独立(仅使用操作系统提供的并发机制) 直接结合 Active Object (Actor Model) 异步方法调用 完全异步 Futures Java: 不纯粹的 Active Object 模型
11
2015/5/8Institute of Computer Software Nanjing University
12
2015/5/8Institute of Computer Software Nanjing University
13
2015/5/8Institute of Computer Software Nanjing University
14
2015/5/8Institute of Computer Software Nanjing University Evaluation Rather rudimentary mechanism Explicit message passing not unified with object/methods model No inheritance Asynchronous message passing How to implement queries, i.e., invocations with replies? Especially with FIFO? Unbounded queues? Sometimes one would like to reason about a larger code portion in sequential case Requires mechanism on top of only asynchronous invocations
15
2015/5/8Institute of Computer Software Nanjing University 在顺序的 Java 对象世界中加上并发的考虑
16
2015/5/8Institute of Computer Software Nanjing University Reminder Concurrency Why Efficiency “The world is concurrent” widely used What Safety Liveness How Mutex, Semaphore, Monitor, Rendez-Vous
17
2015/5/8Institute of Computer Software Nanjing University 下面: 并发基础支撑 并发融入对象模型 同步设施 典型问题
18
2015/5/8Institute of Computer Software Nanjing University Concurrent programming (in Java) Many of the following ppt slides are made by Andy Willings (University of York) Zoltan Papp (Vanderbilt University) Some pictures are from Concurrent Programming in Java™: Design Principles and Patterns, Second Edition. By Doug Lea. Addison Wesley
19
2015/5/8Institute of Computer Software Nanjing University Java 语言并发机制 内置并发机制:对线程的直接支持
20
© Andy Wellings, 2004 Concurrency Models I Processes versus Threads Operating System ThreadsFibresProcess thread library
21
© Andy Wellings, 2004 Concurrency Models II Java supports threads Threads execute within a single JVM Native threads map a single Java thread to an OS thread Green threads adopt the thread library approach (threads are invisible to the OS) On a multiprocessor system, native threads are required to get true parallelism (but this is still implementation dependent)
22
2015/5/8Institute of Computer Software Nanjing University Java 语言并发机制 内置并发机制:对线程的直接支持 并发对象模型:不纯粹的 Active Object 模型 同时存在 “ 主动 ” 对象 和 被动对象 线程间通信?共享对象
23
2015/5/8Institute of Computer Software Nanjing University
24
2015/5/8Institute of Computer Software Nanjing University
25
2015/5/8Institute of Computer Software Nanjing University
26
2015/5/8Institute of Computer Software Nanjing University
27
2015/5/8Institute of Computer Software Nanjing University
28
© Andy Wellings, 2004 Java has a predefined class java.lang.Thread which provides the mechanism by which threads are created However to avoid all threads having to be child classes of Thread, it also uses a standard interface public interface Runnable { public void run(); } Hence, any class which wishes to express concurrent execution must implement this interface and provide the run method Threads do not begin their execution until the start method in the Thread class is called Concurrency in Java
29
© Andy Wellings, 2004 Threads in Java Thread void run() void start()... Thread() Thread(Runnable target) subclass association MyThread void run() {... } RunnableObject void run() {... } parameter to Runnable implements void run()
30
© Andy Wellings, 2004 The Thread Class public class Thread extends Object implements Runnable { public Thread(); public Thread(String name); public Thread(Runnable target); public Thread(Runnable target, String name); public Thread(Runnable target, String name, long stackSize); public void run(); public void start();... }
31
© Andy Wellings, 2004 Thread Creation Either: 1. Extend Thread class and override the run method, or 2. Create an object which implements the Runnable interface and pass it to a Thread object via the Thread constructor How is the run method of Thread implemented?
32
© Andy Wellings, 2004 Thread Creation: Robot Example Robot Motor Controller Thread is driven by User Interface controlled by 31
33
© Andy Wellings, 2004 Classes for Robot public class UserInterface { // Allows the next position of the robot // to be obtained from the operator. public int newSetting (int dim) {... }... } public class Robot { // The interface to the Robot itself. public void move(int dim, int pos) {... } // Other methods, not significant here. } Note in Java 1.5, dimension would be an enumeration type
34
© Andy Wellings, 2004 Motor Controller extends Thread I public class MotorController extends Thread { public MotorController(int dimension, UserInterface UI, Robot robo) { // constructor super(); dim = dimension; myInterface = UI; myRobot = robo; }
35
© Andy Wellings, 2004 Motor Controller extends Thread II public void run() { int position = 0; // initial position int setting; while(true) { // move to position myRobot.move(dim, position); // get new offset and update position setting = myInterface.newSetting(dim); position = position + setting; } private int dim; private UserInterface myInterface; private Robot myRobot; } run method overridden
36
© Andy Wellings, 2004 Motor Controller extends Thread III final int xPlane = 0; final int yPlane = 1; final int zPlane = 2; UserInterface UI = new UserInterface(); Robot robo= new Robot(); MotorController MC1 = new MotorController( xPlane, UI, robo); MotorController MC2 = new MotorController( yPlane, UI, robo); MotorController MC3 = new MotorController( zPlane, UI, robo); threads created
37
© Andy Wellings, 2004 Motor Controller extends Thread IV When a thread is started, its run method is called and the thread is now executable When the run method exits, the thread is no longer executable and it can be considered terminated (Java calls this the dead state) The thread remains in this state until it is garbage collected In this example, the threads do not terminate MC1.start(); MC2.start(); MC3.start();
38
© Andy Wellings, 2004 Warning The run method should not be called directly by the application. The system calls it. If the run method is called explicitly by the application then the code is executed sequentially not concurrently
39
© Andy Wellings, 2004 Motor Controller implements Runnable I is driven by controlled by implements parameter to Robot Runnable MotorController Thread UserInterface
40
© Andy Wellings, 2004 Motor Controller implements Runnable II public class MotorController implements Runnable { public MotorController(int Dimension, UserInterface UI, Robot robo) { // No call to super() needed now, // otherwise constructor is the same. } public void run() { // Run method identical. } // Private part as before. }
41
© Andy Wellings, 2004 Motor Controller implements Runnable III final int xPlane = 0; final int yPlane = 1; final int zPlane = 2; UserInterface UI = new UserInterface(); Robot robo= new Robot(); MotorController MC1 = new MotorController( xPlane, UI, robo); MotorController MC2 = new MotorController( yPlane, UI, robo); MotorController MC3 = new MotorController( zPlane, UI, robo); No threads created yet
42
© Andy Wellings, 2004 Motor Controller implements Runnable IV Thread X = new Thread(MC1); Thread Y = new Thread(MC2); Thread Z = new Thread(MC2); X.start(); Y.start(); Z.start(); constructors passed an object implementing the Runnable interface when the threads are created threads started Note: it is also possible to recommend to the JVM the size of the stack to be used with the thread. However, implementations are allowed to ignore this recommendation.
43
© Andy Wellings, 2004 Thread Identification The identity of the currently running thread can be found using the currentThread method This has a static modifier, which means that there is only one method for all instances of Thread objects The method can always be called using the Thread class public class Thread extends Object implements Runnable {... public static Thread currentThread();... }
44
© Andy Wellings, 2004 A Thread Terminates: when it completes execution of its run method either normally or as the result of an unhandled exception via a call to its stop method — the run method is stopped and the thread class cleans up before terminating the thread (releases locks and executes any finally clauses) the thread object is now eligible for garbage collection. stop is inherently unsafe as it releases locks on objects and can leave those objects in inconsistent states; the method is now deprecated and should not be used by its destroy method being called — destroy terminates the thread without any cleanup (not provided by many JVMs, now deprecated)
45
© Andy Wellings, 2004 Daemon Threads Java threads can be of two types: user threads or daemon threads Daemon threads are those threads which provide general services and typically never terminate When all user threads have terminated, daemon threads can also be terminated and the main program terminates The setDaemon method must be called before the thread is started
46
© Andy Wellings, 2004 Thread Revisited public class Thread extends Object implements Runnable {... public void destroy(); // DEPRECATED public final boolean isDaemon(); public final void setDaemon(); public final void stop(); // DEPRECATED }
47
© Andy Wellings, 2004 Joining One thread can wait (with or without a timeout) for another thread (the target) to terminate by issuing the join method call on the target's thread object The isAlive method allows a thread to determine if the target thread has terminated
48
© Andy Wellings, 2004 Thread Revisited public class Thread extends Object implements Runnable {... public final native boolean isAlive(); public final void join() throws InterruptedException; public final void join(long millis) throws InterruptedException; public final void join(long millis, int nanos) throws InterruptedException; }
49
© Andy Wellings, 2004 Summary I: Java Thread States Non-Existing New Executable Blocked Dead start create thread object run method exits Non-Existing garbage collected and finalization wait, join notify, notifyAll thread termination destroy
50
runnable scheduler Thread state transitions in Java 1.1 and earlier new dead suspendedrunningblocked blocked- susp. new stop start stop stop, term resume suspend resume suspend IO, sleep, wait, join yield, time slice notify, notifyAll, IO compl, sleep exp, join compl. IO compl.
51
Thread state transitions in Java 1.2 runnable scheduler new dead runningblocked new start term IO, sleep, wait, join yield, time slice notify, notifyAll, IO compl, sleep exp, join compl.
52
Reasons for the “clean-up”: stop() and suspend() are inherently unsafe! - they encourage “messy” program structures - coherent “lock” states are difficult (or impossible) to maintain - they can result in corrupted data
53
© Andy Wellings, 2004 Summary II The thread is created when an object derived from the Thread class is created At this point, the thread is not executable — Java calls this the new state Once the start method has been called, the thread becomes eligible for execution by the scheduler If the thread calls the wait method in an Object, or calls the join method in another thread object, the thread becomes blocked and no longer eligible for execution It becomes executable as a result of an associated notify method being called by another thread, or if the thread with which it has requested a join, becomes dead
54
© Andy Wellings, 2004 Summary III A thread enters the dead state, either as a result of the run method exiting (normally or as a result of an unhandled exception) or because its destroy method has been called In the latter case, the thread is abruptly move to the dead state and does not have the opportunity to execute any finally clauses associated with its execution; it may leave other objects locked
55
2015/5/8Institute of Computer Software Nanjing University Java 语言并发机制 内置并发机制:对线程的直接支持 并发对象模型:不纯粹的 Active Object 模型 同时存在 “ 主动 ” 对象 和 被动对象 同步模型:内建的 Monitor
56
2015/5/8Institute of Computer Software Nanjing University 两个要求 使开发者易于达到下面两个目标 Safety. Nothing bad ever happens to an object. Liveness. Something eventually happens within an activity.
57
2015/5/8Institute of Computer Software Nanjing University Safety
58
2015/5/8Institute of Computer Software Nanjing University Liveness
59
2015/5/8Institute of Computer Software Nanjing University
60
2015/5/8Institute of Computer Software Nanjing University Java 语言并发机制 仅有互斥不够 考虑共享的 buffer 判断 buffer 状态和存取 buffer 同步机制: wait, notify, notifyall 条件等待!
61
© Andy Wellings, 2004 Concurrency Models IV Communication and Synchronization approaches broadly classified as shared-variable or message passing many different models, a popular one is a monitor a monitor can be considered as an object where each of its operation executes in mutual exclusion encapsulated state procedural interface lock
62
© Andy Wellings, 2004 Concurrency Models V Condition Synchronization expresses a constraint on the ordering of execution of operations e.g., data cannot be removed from a buffer until data has been placed in the buffer Monitors provide condition variables with two operations which can be called when the lock is held wait: an unconditional suspension of the calling thread (the thread is placed on a queue associated with the condition variable) notify: one thread is taken from the queue and re-scheduled for execution (it must reclaim the lock first) notifyAll: all suspended threads are re-scheduled notify and notifyAll have no effect if no threads are suspended on the condition variable
63
© Andy Wellings, 2004 Communication in Java Via reading and writing to data encapsulated in shared objects protected by simple monitors Every object is implicitly derived from the Object class which defines a mutual exclusion lock Methods in a class can be labeled as synchronized, this means that they can only be executed if the lock can be acquired (this happens automatically) The lock can also be acquired via a synchronized statement which names the object A thread can wait and notify on a single anonymous condition variable
64
© Andy Wellings, 2004 2015/5/8Institute of Computer Software Nanjing University 进一步理解同步机制 分别从 Provider 和 Client 的角度考虑 Java 的 Monitor 锁是计数的
65
Semaphores (locks): resource lock Implementation: primitive data type + operations (atomic) E.g. semaphore + P, V operations V(s): s := s + 1; P(s): if s == 0 then wait_until( s 0 ); s := s - 1;
66
Thread 1: semaphore s1 = 1; /* to protect R1 resource initial value: free */. P(s1);/* lock R1 if available */ V(s1);/* free R1 */. Usage :
67
Example: Semaphores in Java public class Semaphore { long sem; public Semaphore(long init) { sem = init; } public synchronized void P() throws InterruptedException { while ( sem == 0 ) wait(); sem -= 1; } public synchronized void V() { sem += 1; notifyAll(); } public boolean isDown() { return sem == 0; }
68
© Andy Wellings, 2004 Readers/Writers Problem I Many reader threads and many writer threads are attempting to access an object encapsulating a large data structure Readers can read concurrently, as they do not alter the data Writers require mutual exclusion over the data both from other writers and from readers There are different variations on this scheme; the one considered here is where priority is always given to waiting writers Hence, as soon as a writer is available, all new readers will be blocked until all writers have finished Of course, in extreme situations this may lead to starvation of readers
69
© Andy Wellings, 2004 Readers/Writers Problem II Standard solution requires four monitor methods, which are used: startRead(); // call object to read data structure stopRead(); startWrite(); // call object to write data structure stopWrite();
70
© Andy Wellings, 2004 Readers-Writers Problem III Standard solution in monitors is to have two condition variables: OkToRead and OkToWrite This cannot be directly expressed using a single Java monitor public class ReadersWriters { private int readers = 0; private int waitingWriters = 0; private boolean writing = false;
71
© Andy Wellings, 2004 Readers-Writers Problem IV public synchronized void StartWrite() throws InterruptedException { while(readers > 0 || writing) { waitingWriters++; wait(); waitingWriters--; } writing = true; } public synchronized void StopWrite() { writing = false; notifyAll(); } loop to re-test the condition Wakeup everyone
72
© Andy Wellings, 2004 Readers-Writers Problem V public synchronized void StartRead() throws InterruptedException { while(writing || waitingWriters > 0) wait(); readers++; } public synchronized void StopRead() { readers--; if(readers == 0) notifyAll(); } }
73
© Andy Wellings, 2004 Readers-Writers Problem VI On awaking after the wait request, the thread must re- evaluate the conditions under which it can proceed Although this approach will allow multiple readers or a single writer, arguably it is inefficient, as all threads are woken up every time the data becomes available Many of these threads, when they finally gain access to the monitor, will find that they still cannot continue and, therefore, will have to wait again. It should also be noted that this solution is not tolerant to the InterruptedException being thrown (how would you make it tolerant?)
74
© Andy Wellings, 2004 Java 1.5 Concurrency Utilities Java 1.5 has comprehensive support for general-purpose concurrent programming The support is partitioned into three packages: java.util.concurrent - this provides various classes to support common concurrent programming paradigms, e.g., support for various queuing policies such as bounded buffers, sets and maps, thread pools etc java.util.concurrent.atomic - this provides support for lock-free thread-safe programming on simple variables such as atomic integers, atomic booleans, etc. java.util.concurrent.locks - this provides a framework for various locking algorithms that augment the Java language mechanisms, e.g., read -write locks and condition variables.
75
© Andy Wellings, 2004 Locks I package java.util.concurrent.locks; public interface Lock { public void lock(); // Wait for the lock to be acquired. public Condition newCondition(); // Create a new condition variable for // use with the Lock. public void unlock(); … }
76
© Andy Wellings, 2004 Locks II package java.util.concurrent.locks; public interface Condition { public void await() throws InterruptedException; // Atomically releases the associated lock // and causes the current thread to wait. public void signal(); // Wake up one waiting thread. public void signalAll(); // Wake up all waiting threads. … }
77
© Andy Wellings, 2004 Lock III package java.util.concurrent.locks; public class ReentrantLock implements Lock { public ReentrantLock();... public void lock(); public Condition newCondition(); // Create a new condition variable and // associated it with this lock object. public void unlock(); }
78
© Andy Wellings, 2004 Generic Bounded Buffer I import java.util.concurrent.*; public class BoundedBuffer { private Data buffer[]; private int first; private int last; private int numberInBuffer; private int size; private Lock lock = new ReentrantLock(); private final Condition notFull = lock.newCondition(); private final Condition notEmpty = Lock.newCondition();
79
© Andy Wellings, 2004 Generic Bounded Buffer II public BoundedBuffer(int length) { size = length; buffer = (Data[]) new Object[size]; last = 0; first = 0; numberInBuffer = 0; }
80
© Andy Wellings, 2004 Generic Bounded Buffer III public void put(Data item) throws InterruptedException { lock.lock(); try { while (numberInBuffer == size) notFull.await(); last = (last + 1) % size; numberInBuffer++; buffer[last] = item; notEmpty.signal(); } finally { lock.unlock(); }
81
© Andy Wellings, 2004 Generic Bounded Buffer IV public Data get() throws InterruptedException { lock.lock(); try { while (numberInBuffer == 0) notEmpty.await(); first = (first + 1) % size ; numberInBuffer--; notFull.signal(); return buffer[first]; } finally { lock.unlock(); } } }
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.