SSC - Concurrency and Multi-threading Java multithreading programming - Synchronisation (I) Shan He School for Computational Science University of Birmingham Module 06-19321: SSC
Outline Outline of Topics Review what we learned Synchronising Threads
thread process emory segments Other Data resources Multithreaded process Code Data Other resources Stack Register Register Register Stack Stack Stack
Problems will arise when multiple threads access the shared resources: Q: How threads communicate/coordinate? A: Essentially by sharing the same memory space, e.g., access to fields and the objects reference fields refer to. Efficient, but makes two kinds of errors possible: Thread interference Memory consistency errors Note: Critical section - a piece of code that accesses a shared resource
Thread interference Also called race conditions Errors are introduced when multiple threads access and try to change the same resource, e.g., memory (variables, arrays, objects), system (databases) or file Let s take a look a very simple example: adding/subtracting some values from 0. We first define a Class Counter to do adding/subtracting Suppose we want to reference a Counter object from two threads which add 1 and then subtract 1. We expect we should get the outputs of 0 from both threads, but sometimes it is not. Why?
Atomic operations Atomic operation: an action either happens completely, or it doesn t happen at all. Even for a simple add() method, there are three atomic operations: Step 1: Load value from counter into a register Step 2: Add some value to the register Step 3: Store the value in the register back to counter
Thread interference Simple example: two threads try to increase an integer value by 1 (and later both decrease the vaule by 1) The steps when it went wrong: Thread 1 Thread 2 Integer value 0 read value to r1 0 read value to r2 0 increase value in r1 0 increase value in r2 0 write back 1 write back 1 Step 1: Load integer value to a register Step 3: Store the register to integer vaule
Thread interference: danger and solution Please read and execute my code example for thread interference. You might notice most of the time it runs perfectly well This kind of bug is particularly difficult to find and fix One solution: Synchronisation, that is enforcing exclusive access to a shared resource.
Memory consistency errors Memory consistency errors: different threads have inconsistent views of the same data. Example: Suppose we have one int field: int count = 0; counter is shared between two threads A and B Thread A increments counter: Thread B simply prints out counter: System.out.println(counter); The output might not be predictable. count++; No guarantee that thread A s change to counter will be visible to thread B
Memory consistency errors Memory consistency errors VS. thread interference Thread interference: happens when different threads are changing the same data Memory consistency errors: happens when different threads have different views of the same shared data. The causes of these errors are complex: we only need to know how to avoid them Key for avoiding these errors: understanding the happens-before relationship, also denoted as a b: event a should happen before event b, the result must reflect that no matter what order those events are in reality executed. A guarantee that memory written to by statement A is visible to statement B, that is, that statement A completes its write before statement B starts its read.
Ways of creating happens-before relationships for thrads For threads share the same data, we need to write code to explicitly implement happens-before relationships, esp. for executing new threads In Java, we can use Thread.join() Please take a look at my Java example Synchronisation
Synchronising Threads Synchronisation in Java Three tools for Synchronization: Locks: the most common synchronization tool Volatile Variables: establishes a happens-before relationship to solve the memory consistency errors Atomic Operations: nonblocking synchronization, ensure an action either happens completely, or it doesn t happen at all to solve the thread interference problem Two ways of using locks: Reentrant Locks, and Synchronized keyword Two ways of using Synchronized keyword in Java: Synchronized methods, and Synchronized statements/blocks Differences: simply put, synchronized methods are simpler but less flexible Please see two Java examples
Synchronising Threads Mechanisms behind Java synchronisation: Intrinsic lock Synchronization is built around an internal entity known as the intrinsic lock, or monitor lock, or simple lock. In Java, every object has an intrinsic lock associated with it Intrinsic lock does two things: enforcing exclusive access to an object s state; and establishing happens-before relationships How it works: Thread A acquires the object s intrinsic lock before accessing the object s field exclusive access No other thread can acquire the same lock before Thread A releases the lock happens-before relationships accessing It release the intrinsic lock when finishes
Synchronising Threads Mechanisms behind Java synchronisation: monitor An important concept in concurrent programming and operating system Monitor: a synchronization mechanism that allows threads: to have mutual exclusion to have the ability to wait for a certain condition to become true to signal other threads that their condition has been met. A monitor can be formally defined as M = (m, c), where m is intrinsic lock object and c a condition variable. Intrinsic lock m: ensures exclusive access and happens-before relationships Condition c: ensures threads attempting an operation to wait until some condition, e.g., job queue is not empty, is met A monitor is basically a container of threads that are waiting on a certain condition.
Synchronising Threads Mechanisms behind Java synchronisation: monitor Meeting room (monitor region) Bank (Monitor) Step 3: Release Some object with intrinsic lock Waiting room (waiting set) Step 5: release and exit Step 4: Acquire Step 2: If not occupied, occupy monitor region If occupied, entre waiting set Hallway (Entry set) Some scheduling: FIFO An active thread A waiting thread Step 1: entre entry set