Presentation is loading. Please wait.

Presentation is loading. Please wait.

Modernās Programmēšanas Tehnoloģijas (Advanced Programming Technologies) Edgars Celms, Mārtiņš Opmanis Latvijas Universitātes Matemātikas.

Similar presentations


Presentation on theme: "Modernās Programmēšanas Tehnoloģijas (Advanced Programming Technologies) Edgars Celms, Mārtiņš Opmanis Latvijas Universitātes Matemātikas."— Presentation transcript:

1 Modernās Programmēšanas Tehnoloģijas (Advanced Programming Technologies) Edgars Celms, Mārtiņš Opmanis Latvijas Universitātes Matemātikas un informātikas institūts 2007, Rīga, Latvija

2 Daudzpavedienu (multithreading) programmēšana valodā JAVA “Java™ How to Program, Sixth Edition”  Chapter 23. Multithreading Pavedienu stāvokļi, pavedienu dzīves cikls Pavedienu prioritātes un to aktivēšana (scheduling) Pavedienu izveidošana un izpilde Pavedienu sinhronizācija Daudzpavedienu programmēšana un GUI Pakotne java.util.concurrent Monitori valodā JAVA

3 Ievads Daudzpavedienu programmēšana (multithreading)  Nodrošina lietojumprogrammām iespēju strādāt ar daudziem izpildes pavedieniem (threads of execution)  Dod iespēju programmai izpildīt uzdevumus paralēli  Šādi programmējot bieži rodas nepieciešamība pēc pavedienu sinhronizācijas, lai nodrošinātu vēlamo funkcionalitāti

4 Dažas piezīmes I (Software Engineering Observation) A problem with single-threaded applications is that lengthy activities must complete before other activities can begin. In a multithreaded application, threads can be distributed across multiple processors (if they are available) so that multiple tasks are performed concurrently and the application can operate more efficiently. Multithreading can also increase performance on single-processor systems that simulate concurrency – when one thread cannot proceed, another can use the processor. Unlike languages that do not have built-in multithreading capabilities (such as C and C++) and must therefore make nonportable calls to operating system multithreading primitives, Java includes multithreading primitives as part of the language itself and as part of its libraries. This facilitates manipulating threads in a portable manner across platforms.

5 Pavedienu stāvokļi, pavedienu dzīves cikls Pavedienu stāvokļi (thread states)  new stāvoklis Pavediens sāk savu dzīves ciklu ar new state Atrodas šajā stāvoklī līdz tam brīdim kad programma to startē un “pārved” to runnable stāvoklī  runnable stāvoklis Pavediens šajā stāvoklī izpilda savu uzdevumu  waiting stāvoklis Pavediens nonāk šai stāvoklī ja tam ir jāgaida uz kādu citu pavedienu līdz tas paveiks kādu uzdevumu  timed waiting stāvoklis Pavediens nonāk šai stāvoklī ja tam ir jāgaida uz kādu citu pavedienu vai arī tam ir jāgaida uz laika intervālu kurā tas varētu izpildīties Pavediens no šī stāvokļa atgriežas runnable stāvoklī, ja tas saņem signālu no cita pavediena vai arī sagaida savu laika intervālu  terminated stāvoklis runnable stāvoklī esošs pavediens nonāk šajā stāvoklī pēc sava uzdevuma izpildīšanas

6 Pavedienu stāvokļi, pavedienu dzīves cikls Pavedienu dzīves cikls attēlots ar UML stāvokļu diagrammu (state diagram)

7 Pavedienu stāvokļi, pavedienu dzīves cikls Operāciju sistēmas skats uz pavediena runnable stāvokli  ready stāvoklis Pavediens šajā stāvoklī negaida uz citu pavedienu, bet gan gaida kamēr operāciju sistēma izdalīs procesora laiku  running stāvoklis Pavedienam šajā stāvoklī tiek reāli izpildīts (izmanto procesora laiku)  A thread in the running state often executes for a small amount of processor time called a time slice or quantum before transitioning back to the ready state Operating system’s internal view of Java’s runnable state

8 Pavedienu prioritātes un to aktivēšana (Thread Priorities and Thread Scheduling) Prioritātes  Katram Javas pavedienam ir prioritāte  Prioritātes ir robežās no MIN_PRIORITY (vērtība 1) un MAX_PRIORITY (vērtība 10)  Pavedieni ar lielāku prioritāti ir “svarīgāki” un piekļūs procesora resursiem pirms pavedieniem ar zemāku prioritāti  Prioritāte pēc noklusēšanas ir NORM_PRIORITY (konstante 5) Pavedienu aktivētājs (thread scheduler)  Nosaka kuram pavedienam ir jāstrādā kā nākamajam Vienkāršākā implementācija ir tā saucamais apļkārtes (round-robin) princips vienādas prioritātes pavedieniem Augstākas prioritātes pavedieni var “pārpirkt (pārņemt)” (preempt) tekošo running stāvoklī esošu pavedienu Dažos gadījumos augstākas prioritātes pavedieni var nedefinēti aizkavēt zemākas prioritātes pavedienus – tiek saukta arī par “badošanos” (starvation)

9 Dažas piezīmes II (Software Engineering Observation) Thread scheduling is platform dependent – an application that uses multithreading could behave differently on separate Java implementations. When designing applets and applications that use threads, you must consider the threading capabilities of all the platforms on which the applets and applications will execute. Thread-priority scheduling.

10 Pavedienu izveidošana un izpilde Runnable interfeiss  Izmanto, lai veidotu daudzpavedienu lietojumprogrammas  Deklarē run metodi  Izpilda objekts kurš implementē Executor interfeisu Executor interfeiss  Deklarē execute metodi  Izveido un pārvalda pavedienu grupu – tiek saukta par thread pool ExecutorService interfeiss  Executor apakšinterfeiss kurā ir deklarētas citas metodes, kuras pārvalda Executor dzīves ciklu  Objektus var radīt izmantojot atbilstošās klases Executors static metodes  Metode shutdown pabeidz pavedienus ja uzdevumi ir pabeigti Executors klase  Metode newFixedThreadPool izveido thread pool no fiksēta skaita pavedieniem  Metode newCachedThreadPool izveido thread pool, kurš rada jaunus pavedienus pēc vajadzības

11 Implement runnable to create separate thread

12 Declare run method to fulfill interface Invoke static method sleep of class Thread to place the thread into the timed waiting state. At this point, the thread loses the processor, and the system allows another thread to execute. When the thread awakens, it reenters the runnable state

13 Create three PrintTask s; each will run in a separate thread Create fixed thread pool to execute and manage threads Execute each task; this method will assign a thread to the runnable Shutdown thread pool when runnable s complete their tasks

14

15 Pavedienu sinhronizācija (thread synchronization) Pavedienu sinhronizācija  Valodā Java programmētājam tiek dota iespēja izmantot mutual exclusion mehānismu Dod iespēju ekskluzīvi (vienam pašam) strādāt ar kopīgiem (shared) objektiem Mutual exclusion (often abbreviated to mutex) algorithms are used in concurrent programming to avoid the simultaneous use of un-shareable resources by pieces of computer code called critical sections.  Javā tas tiek implementēts izmantojot aiztures (locks) Lock interfeiss  lock metode uzstāda aizturi (lock) un iedarbina mutual exclusion  unlock metode atbrīvo aizturi (lock)  Klase ReentrantLock implementē Lock interfeisu The constructor for a ReentrantLock takes a boolean argument that specifies whether the lock has a fairness policy. If this is set to true, the ReentrantLock's fairness policy states that the longest-waiting thread will acquire the lock when it is available. If this is set to false, there is no guarantee as to which waiting thread will acquire the lock when it is available.

16 Pavedienu sinhronizācija (thread synchronization) Nosacījuma mainīgie (condition variables)  Ja pavediens, kuram ir aizture (holding the lock) nevar izpildīt savu uzdevumu dēļ tā, ka kāds nosacījums nav izpildījies, tad pavediens var gaidīt līdz nosacījums ir izpildījies  Nosacījuma mainīgos var izveidot izsaucot Lock metodi newCondition  Tiek reprezentēts ar objektu kurš implementē Condition interfeisu Condition interfeiss  Deklarē metodes await – liek pavedienam gaidīt signal – lai “pamodinātu” (wake up) gaidošo pavedienu signalAll – lai “pamodinātu” visus gaidošos pavedienus

17 Populārākās programmēšanas kļūdas I (Common Programming Error) Deadlock occurs when a waiting thread (let us call this thread1) cannot proceed because it is waiting (either directly or indirectly) for another thread (let us call this thread2) to proceed, while simultaneously thread2 cannot proceed because it is waiting (either directly or indirectly) for thread1 to proceed. Two threads are waiting for each other, so the actions that would enable each thread to continue execution never occur. It is an error if a thread issues an await, a signal, or a signalAll on a condition variable without having acquired the lock for that condition variable. This causes an IllegalMonitorStateException.

18 Dažas piezīmes II (Software Engineering Observation) When multiple threads manipulate a shared object using locks, ensure that if one thread calls method await to enter the waiting state for a condition variable, a separate thread eventually will call Condition method signal to transition the thread waiting on the condition variable back to the runnable state. If multiple threads may be waiting on the condition variable, a separate thread can call Condition method signalAll as a safeguard to ensure that all the waiting threads have another opportunity to perform their tasks. If this is not done, indefinite postponement or deadlock could occur. The locking that occurs with the execution of the lock and unlock methods could lead to deadlock if the locks are never released. Calls to method unlock should be placed in finally blocks to ensure that locks are released and avoid these kinds of deadlocks. Performance tip. Using a Lock with a fairness policy helps avoid indefinite postponement, but can also dramatically reduce the overall efficiency of a program. Because of the large decrease in performance, fair locks are only necessary in extreme circumstances. Performance tip. Synchronization to achieve correctness in multithreaded programs can make programs run more slowly, as a result of thread overhead and the frequent transition of threads between the waiting and runnable states.

19 Ražotāja/patērētāja attiecība (producer/consumer relationship) bez sinhronizācijas Ražotāja/patērētāja attiecība  Ražotājs ģenerē datus un glabā tos kopīgā atmiņas apgabalā (shared memory)  Patērētājs lasa saražotos datus no kopīgā atmiņas apgabala  Kopīgo atmiņas apgabalu sauksim par buferi (buffer)

20 Implement the runnable interface so that producer will run in a separate thread Declare run method to satisfy interface

21 Sleep for up to 3 seconds

22 Implement the runnable interface so that producer will run in a separate thread Declare run method to satisfy interface

23 Sleep for up to 3 seconds

24 Shared variable to store data Set the value of the buffer Read the value of the buffer

25 Create shared UnsynchronizedBuffer for producer and consumer to use

26 Pass shared buffer to both producer and consumer

27

28

29 Ražotāja/patērētāja attiecība (producer/consumer relationship) ar sinhronizāciju Ražotāja/patērētāja attiecība ar sinhronizāciju  Piemērā tiek izmantots Locks un Conditions, lai implementētu sinhronizāciju

30 Create ReentrantLock for mutual exclusion Create two Condition variables; one for writing and one for reading Buffer shared by producer and consumer Try to obtain the lock before setting the value of the shared data

31 Producer waits until buffer is empty

32 Signal consumer that it may read a value Release lock on shared data Acquire lock before reading a value

33 Consumer waits until buffer contains data to read

34 Signal producer that it can write to buffer Release lock on shared data

35 Create SynchronizedBuffer to be shared between producer and consumer

36 Execute the producer and consumer in separate threads

37

38

39 Populārākās programmēšanas kļūdas II (Common Programming Error) Place calls to Lock method unlock in a finally block. If an exception is thrown, unlock must still be called or deadlock could occur. Forgetting to signal a thread that is waiting for a condition is a logic error. The thread will remain in the waiting state, which will prevent the thread from doing any further work. Such waiting can lead to indefinite postponement or deadlock.

40 Dažas piezīmes III (Software Engineering Observation) Always invoke method await in a loop that tests an appropriate condition. It is possible that a thread will reenter the runnable state before the condition it was waiting on is satisfied. Testing the condition again ensures that the thread will not erroneously execute if it was signaled early.

41 Ražotāja/patērētāja attiecība (producer/consumer relationship) izmantojot riņķveda (circular) buferi Iepriekšējos piemēros neoptimāls laika sadalījums, ja plūsmas izpilda savus uzdevumus ar dažādiem ātrumiem Riņķveida buferis (circular buffer)  Tiek nodrošināts kopīgs atmiņas apgabals (programmējama izmēra), kurā ražotājs var ievietot vērtības un patērētājs var šīs vērtības nolasīt

42 Dažas piezīmes IV (Software Engineering Observation) Performance tip.Even when using a circular buffer, it is possible that a producer thread could fill the buffer, which would force the producer thread to wait until a consumer consumes a value to free an element in the buffer. Similarly, if the buffer is empty at any given time, the consumer thread must wait until the producer produces another value. The key to using a circular buffer is to optimize the buffer size to minimize the amount of thread wait time.

43 Lock to impose mutual exclusionCondition variables to control writing and reading Circular buffer; provides three spaces for data Obtain the lock before writing data to the circular buffer

44 Wait until a buffer space is empty Update index; this statement imposes the circularity of the buffer Signal waiting thread it can now read data from buffer Release the lock

45 Lock the object before attempting to read a value Wait for a value to be written to the buffer Update read index; this statement imposes the circularity of the buffer

46 Signal thread waiting to write to the buffer Release the lock

47

48 Create CircularBuffer for use in both the producer and consumer Execute the producer and consumer in separate threads

49

50

51

52 Ražotāja/patērētāja attiecība (producer/consumer relationship) izmantojot ArrayBlockingQueue Klase ArrayBlockingQueue  Riņķveida bufera implementācija valodā Java  Implementē BlockingQueue interfeisu  Deklarē metodes put un take, lai varētu rakstīt un lasīt datus buferī

53 Create instance of ArrayBlockingQueue to store data Place a value into the buffer; blocks if buffer is full

54 Remove value from buffer; blocks if buffer is empty

55 Create BlockingBuffer for use in producer and consumer Execute the producer and consumer in separate threads

56

57 Daudzpavedienu programmēšana un GUI Swing GUI komponentes  Nav pavedienu drošas  Izmaiņas ir jāveic event-dispatching pavedienā (tiek saukts arī par event-handling pavedienu) Lai realizētu var lietot klases SwingUtilities static metodi invokeLater nododot tai objektu, kurš implementē Runnable interfeisu

58 Implement the Runnable interface Lock to implement mutual exclusion Condition variable for suspending the threads Boolean to control whether thread is suspended Create the Lock and a Condition variable Get name of current thread

59 Obtain the lock to impose mutual exclusion Wait while thread is suspended Release the lock

60 Call invokeLater Method invokeLater is passed a Runnable

61 Obtain lock for the applicationResume a waiting threadRelease the lock

62 Create Lock for the application

63 Create thread pool for executing threads

64 Execute a Runnable Shutdown thread pool when threads finish their tasks

65

66 Dažas piezīmes V (Software Engineering Observation) The Runnable interface provides only the most basic functionality for multithreaded programming. In fact, this interface has several limitations.  Suppose a Runnable encounters a problem and tries to throw a checked exception. The run method is not declared to throw any exceptions, so the problem must be handled within the Runnable. The exception cannot be passed to the calling thread.  Now suppose a Runnable is performing a long calculation and the application wants to retrieve the result of that calculation. The run method cannot return a value, so the application must use shared data to pass the value back to the calling thread. This also involves the overhead of synchronizing access to the data. The developers of the new concurrency APIs in J2SE 5.0 recognized these limitations and created a new interface to fix them. The Callable interface (package java.util.concurrent) declares a single method named call. This interface is designed to be similar to the Runnable interface allowing an action to be performed concurrently in a separate thread but the call method allows the thread to return a value or to throw a checked exception.

67 Citas klases java.util.concurrent pakotnē Callable interfeiss  Deklarē call metodi  Metode call dod iespēju paralēlam uzdevumam atgriezt vērtību vai arī izveidot izņēmumgadījuma situāciju (throw an exception)  ExecutorService metodei submit ir Callable parametrs un tā atgriež Future, kas reprezentē uzdevuma rezultātu Future interfeiss  Deklarē get metodi  Metode get atgriež uzdevuma rezultātu

68 Monitori valodā JAVA (monitors and monitor locks) Monitori (monitors)  Katram Javas objektam ir monitors  Atļauj vienlaicīgi izpildīties tikai vienam pavedienam synchronized instrukcijas iekšienē synchronized ( object ) { statements } // end synchronized statement  Pavedieni kuri gaida, lai iegūtu monitora aizturi (lock) tiek novietoti blocked stāvoklī  Object metode wait novieto pavedienu waiting stāvoklī  Object metode notify “pamodina” waiting stāvoklī esošu pavedienu  Object metode notifyAll “pamodina” visus waiting stāvoklī esošus pavedienus  Javā ir iespējamas arī sinhronizētas metodes (synchronized methods). Sinhronizēta metode ir ekvivalenta tam, ja synchronized instrukcija būtu iekļāvusi visu metodes ķermeni

69 Dažas piezīmes VI (Software Engineering Observation) The locking that occurs with the execution of synchronized methods could lead to deadlock if the locks are never released. When exceptions occur, Java’s exception mechanism coordinates with Java’s synchronization mechanism to release locks and avoid these kinds of deadlocks.

70 Populārākās programmēšanas kļūdas III (Common Programming Error) It is an error if a thread issues a wait, a notify or a notifyAll on an object without having acquired a lock for it. This causes an IllegalMonitorStateException.

71 Declare a synchronized set method Wait until buffer is emptySet buffer value

72 Buffer is now occupied Notify waiting thread that it may now read a value Declare synchronized get method Wait until buffer is full

73 Buffer is now empty Notify thread it may now write to buffer

74 Create SynchronizedBuffer for use in producer and consumer Execute the producer and consumer in separate threads

75

76

77 Jautājumi ?


Download ppt "Modernās Programmēšanas Tehnoloģijas (Advanced Programming Technologies) Edgars Celms, Mārtiņš Opmanis Latvijas Universitātes Matemātikas."

Similar presentations


Ads by Google