Fix race in inflating thin locks.

Before we were inflating the lock word in the blocked state, this
meant that the garbage collector could be running at this point
resulting in the lock word changing from underneath us.

Bug: 14881707
Change-Id: If8897b2572a1b29a3cf44e5eb2e11c186236f519
diff --git a/runtime/monitor.cc b/runtime/monitor.cc
index 822e0fb..64edba8 100644
--- a/runtime/monitor.cc
+++ b/runtime/monitor.cc
@@ -642,21 +642,22 @@
   } else {
     ThreadList* thread_list = Runtime::Current()->GetThreadList();
     // Suspend the owner, inflate. First change to blocked and give up mutator_lock_.
-    ScopedThreadStateChange tsc(self, kBlocked);
     self->SetMonitorEnterObject(obj.Get());
-    if (lock_word == obj->GetLockWord(true)) {  // If lock word hasn't changed.
-      bool timed_out;
-      Thread* owner = thread_list->SuspendThreadByThreadId(owner_thread_id, false, &timed_out);
-      if (owner != nullptr) {
-        // We succeeded in suspending the thread, check the lock's status didn't change.
-        lock_word = obj->GetLockWord(true);
-        if (lock_word.GetState() == LockWord::kThinLocked &&
-            lock_word.ThinLockOwner() == owner_thread_id) {
-          // Go ahead and inflate the lock.
-          Inflate(self, owner, obj.Get(), hash_code);
-        }
-        thread_list->Resume(owner, false);
+    bool timed_out;
+    Thread* owner;
+    {
+      ScopedThreadStateChange tsc(self, kBlocked);
+      owner = thread_list->SuspendThreadByThreadId(owner_thread_id, false, &timed_out);
+    }
+    if (owner != nullptr) {
+      // We succeeded in suspending the thread, check the lock's status didn't change.
+      lock_word = obj->GetLockWord(true);
+      if (lock_word.GetState() == LockWord::kThinLocked &&
+          lock_word.ThinLockOwner() == owner_thread_id) {
+        // Go ahead and inflate the lock.
+        Inflate(self, owner, obj.Get(), hash_code);
       }
+      thread_list->Resume(owner, false);
     }
     self->SetMonitorEnterObject(nullptr);
   }