title: Android Thread Blocking UI Unless Using Synchronized
body: <p>I was trying to figure out the fastest rate at which my phone's camera could take pictures. The object I use to manage the camera (without the camera logic) looks like this:</p>
  
  <pre><code>public class PictureTaker {
      private boolean mIsTakingPicture;
  
      public void takePicture() {
          mIsTakingPicture = true;
      }
  
      public boolean isTakingPicture() {
          return mIsTakingPicture;
      }
  } 
  </code></pre>
  
  <p>In my activity, I create a new thread and post a runnable to it to start looping and taking pictures when the user taps a button. I stop the thread by tapping the button again.</p>
  
  <pre><code>import android.os.Handler;
  import android.os.HandlerThread;
  import android.support.v7.app.ActionBarActivity;
  import android.os.Bundle;
  import android.util.Log;
  import android.view.View;
  import android.widget.Button;
  
  public class CameraTestActivity extends ActionBarActivity {
  
      private HandlerThread mThread;
      private Handler mThreadHandler;
      private volatile boolean mTestingCameraSpeed;
      private PictureTaker mPictureTaker;
  
      @Override
      protected void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
          setContentView(R.layout.activity_camera_test);
  
          mThread = new HandlerThread("testThread");
          mThread.start();
          mThreadHandler = new Handler(mThread.getLooper());
          mPictureTaker = new PictureTaker();
      }
  
      public void toggleDoingStuff(final View view) {
          Button b = (Button)view;
          if(mTestingCameraSpeed) {
              mTestingCameraSpeed = false;
              b.setText("Start camera");
          } else {
              mTestingCameraSpeed = true;
  
              mThreadHandler.post(new Runnable() {
                  public void run() {
                      loopUntilStop();
                  }
              });
              b.setText("Stop camera");
          }
      }
  
      private void loopUntilStop() {
          for(;;) {
              if(!mTestingCameraSpeed) break;
  
              if(!mPictureTaker.isTakingPicture()) {
                  Log.d("CameraTestActivity", "Taking picture at time " + System.currentTimeMillis());
                  mPictureTaker.takePicture();
              }
          }
      }
  } 
  </code></pre>
  
  <p>Since booleans are atomic and I don't mind missing an update, I didn't wrap the check for <code>mIsTestingCameraSpeed</code> in <code>loopUntilStop()</code> in a <code>synchronized</code> block. (<strong>EDIT:</strong> as mttdbrd and Kevin Krumwiede pointed out, without synchronization or making the variable volatile, the thread might not see the changes).</p>
  
  <p>Anyway, the above code blocks the UI thread. However, changing <code>takePicture()</code> to</p>
  
  <pre><code>public void takePicture() {
      mIsTakingPicture = false;
  }
  </code></pre>
  
  <p>doesn't block the UI, but then <code>mIsTakingPicture</code> isn't set correctly. To prevent blocking and use the first version of <code>takePicture()</code>, I had to change <code>isTakingPicture()</code> to use a lock:</p>
  
  <pre><code>public boolean isTakingPicture() {
      synchronized (this) {
          return mIsTakingPicture;
      }
  }
  </code></pre>
  
  <p>Why would not using a lock block the UI when <code>mIsTakingPicture</code> is set to <code>true</code> but not <code>false</code>? I checked the <a href="http://docs.oracle.com/javase/tutorial/essential/concurrency/locksync.html" rel="nofollow noreferrer">Java documentation on intrinsic locks and synchronization</a> and didn't find anything that would explain it. I've also had a look at these SO questions and none of them answered my question:</p>
  
  <ul>
  <li><a href="https://stackoverflow.com/questions/15247915/android-ui-thread-blocked">Android :UI Thread Blocked</a></li>
  <li><a href="https://stackoverflow.com/questions/6219597/thread-blocks-my-android-ui">Thread blocks my Android UI</a></li>
  <li><a href="https://stackoverflow.com/questions/17845388/thread-blocking-ui-in-android">Thread blocking UI in android</a></li>
  <li><a href="https://stackoverflow.com/questions/16497560/android-asynchronous-post-blocking-ui-thread-still">Android asynchronous post blocks UI thread</a></li>
  <li><a href="https://stackoverflow.com/questions/15001726/android-ui-thread-block-when-calling-asynchtask-get">Android UI Thread Block when calling AsynchTask.get()</a></li>
  <li><a href="https://stackoverflow.com/questions/16625632/load-textures-into-a-thread-blocks-the-mainui-in-android">load textures into a thread blocks the mainUI in android</a></li>
  </ul>
  
  <p><strong>EDIT:</strong> <a href="http://pastebin.com/kZ5K8SWq" rel="nofollow noreferrer">Here</a> are the logs for the ANR. The first two lines indicate that the thread is suspended waiting for a lock, and looking at line 216, it seems that the test thread does acquire a lock at some point. Starting at line 161 of thread_list.cc, the OS tries to acquire two different mutexes, but I'm not sure if those are related to the problem.</p>