Mutex & Cooperation in Dalvik
Understanding Monitor
Haifeng Li
2014-1-6
Outline
• Background
• How To: Implement in Dalvik
• Optimization: Thin Lock & Fat Lock
2
Why Need Mutex?
• A snippets about Xiao ming
3
Why Need Cooperation
• A snippets about writer & reader
4
The Graphical Depiction of Monitor
Entry Wait
Enter
A Waiting Thread
An Active Thread
Acquire
releaseacquire
Owner
Release & exit
12
3
45
5
∙ The picture is from inside the java machine, Figure 20-1.
How to Implement them?
• Mutex -- Synchronized
• Cooperation -- wait() & notify()
6
Key Structure
struct Monitor { Thread* owner; /* which thread currently owns the lock? */ int lockCount; /* owner's recursive lock depth */ Object* obj; /* what object are we part of [debug only] */ Thread* waitSet; /* threads currently waiting on this monitor */ pthread_mutex_t lock; Monitor* next; … };
7
Locking Algorithm (1)
• Lock Monitor without Contention
Thread A will lock a unlocked object
– Call pthread_mutex_lock to Lock monitor->lock
– Set monitor->owner = Thread A
8
Locking Algorithm (2)
• Locking with Contention
Thread B tries to acquire a lock held by thread A. • B ’s check that B owns the lock will fail
• B call pthread_mutex_lock() to acquire monitor->lock. If fail, B sleep on monitor->lock.
9
Cooperation Algorithm (1)
• Thread A grasp the monitor and will wait. – Append self to monitor->waitSet – Store monitor->lockcount – Clear monitor->owner – Update thread status to THREAD_WAIT – Call pthread_mutex_lock to lock thread->waitmutex – Set thread->waitMonitor = monitor – Call pthread_mutex_unlock to unlock the monitor – Call pthread_cond_wait to be scheduled.
P.S.: pthread_cond_wait will call pthread_mutex_unlock
10
Cooperation Algorithm (2)
• Thread B grasp the monitor and notify a thread.
– Thread B traverse monitor->waitSet, if there is a thread, call pthread_cond_signal to wakeup.
11
Cooperation Algorithm (3)
• Thread A was notified by one Thread.
– Pthread_mutex_lock thread->waitMutex
– Clear thread->waitMonitor
– Pthread_mutex_unlock thread->waitMutex
– Reacquire the monitor
– Set monitor->owner
– Restore monitor->lockCount
– Update thread status to THREAD_RUNNING
12
Optimization: Thin Lock & Fat Lock
• Every object should maintenance a monitor. The monitor occupy object->lock and itself.
• But someone found that median of 80% of all lock operations are on unlocked objects, or nesting is very shallow. – Locking an unlocked object
– Locking an object already locked by current thread a small number of times (shallow nested locking)
– Locking an object already locked by the current thread many times (deeply nested locking)
13
• Result is from paper, David F.Bacon etc., Thin locks: feather weight Synchronization for Java.
14
Thin Lock
• Thin lock reuse object->lock, and the layout is as follows.
– Count: Nested lock count
– Thread id: is a identifier. Not System thread id.
– LSB: 0 indicates thin lock.
15
Thread idCount Hash state 0
31 19 3 0
Fat Lock
16
• Object->lock layout is as below.
– LSB: 1 indicates fat lock.
Monitor Pointer Hash state 1
31 3 0
Monitor
Locking Algorithm (1)
• Locking without Contention
– Initially - lock field is 0, thread A wishes to lock.
– If succeeds, object won’t be locked by another thread and we now own lock
17
Locking Algorithm (2)
• Locking with Contention(Lock is thin)
Thread B tries to acquire a lock held by thread A. – B ’s check that B owns the lock will fail
– B needs to force a transition from thin to fat • B enters a spin-locking loop
• Once A unlocks, B will obtain
• B creates a fat lock, assigns object->lock to new monitor
• B changes object->lock to 1
18
Locking Algorithm (3)
• Locking with Contention(Lock is fat)
Thread B tries to acquire a lock held by thread A. • B ’s check that B owns the lock will fail
• B call pthread_mutex_lock() to acquire monitor->lock. If fail, B sleep on monitor->lock.
19
Cooperation Algorithm
• Thread A grasp the thin lock and will wait.
– Fatten the lock firstly
– …
20