Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does the android.os.Handler class eliminate the need to declare certain methods as synchronized?

In putting together a simple "Clock" application I discovered that Android requires you to use android.os.Handler that lives in Thread A in order to update View objects in Thread A with the results of data that come from Thread B.

I'm still relatively new to Java, and this is the first time I've dealt explicitly with Threads before, but I know that ordinarily you'd declare methods and/or operations as synchronized if two different threads want to access the same data. It appears though, that android.os.Handler is an Android-specific way of synchronizing data between threads such that you avoid the classic concurrency errors detailed in the Oracle documentation I just linked to. Is this really true?

If I were to find myself in a situation such that I were required by the Android OS to use android.os.Handler to ferry data from one thread to another, does that mean I don't have to declare the methods used to derive that data as synchronized?

like image 507
scriptocalypse Avatar asked Mar 04 '11 18:03

scriptocalypse


2 Answers

My understanding:

A Handler is just a mechanism for delivering information between two threads. It's not the only mechanism, but it is the mechanism Google chose to use for adding easy to use methods to Activities to do common tasks.

From the doc

When a process is created for your application, its main thread is dedicated to running a message queue that takes care of managing the top-level application objects (activities, broadcast receivers, etc) and any windows they create. You can create your own threads, and communicate back with the main application thread through a Handler. This is done by calling the same post or sendMessage methods as before, but from your new thread. The given Runnable or Message will then be scheduled in the Handler's message queue and processed when appropriate.

The main thread is running a Handler. The handler is responsible for running your activities and managing the application environment. The Handler is just a message loop which dispatches things from a MessageQueue. This is why your thread has to be running a Looper to create a Handler. To synchronize other stuff you want to do with this effort, you have to insert your requests into this message queue so the main application thread does your work. The ui is written so as long as only one thread accesses the objects, it functions.

I guess the point of this was to point out that the Handler is one mechanism for doing synchronization. Surely, the internals of the MessageQueue are written to take synchronization into account, though its a gross simplification to say 'if multiple threads access it it needs to be synchronized.' Although the UI is the most frequent example, using a Handler and Looper is simply a mechanism for designing a multi-threaded application which provides single thread synchronization for the processing of events.

Whether or not you need to synchronize what you send to a Handler depends greatly on what you are sending. If you are talking about synchronizing the calls to post stuff, then no, the handler takes care of that. If you're talking about code inside a Runnable that you post to a Handler, realize that the only guarantee of the Handler is that your runnable will be executed using the thread that created the Handler. You will need to continue to provide synchronization with other resources.

like image 189
Nick Campion Avatar answered Sep 28 '22 03:09

Nick Campion


You only ever need synchronized if you have a shared resource, like an ArrayList or something that can be read from two threads at the same time.

The Handler by itself doesn't prevent any concurrency, it just makes it a lot easier to perform things that need to happen in the UI thread even though a worker thread is trying to do them.

To answer your question: If you use a Handler, it typically means that you do certain critical things in the UI thread. As an example, you have an ArrayList that you initialize in onCreate and then maybe update in a click handler or something. Now if you use a Handler to modify that, then ALL access to the ArrayList will occur in the UI thread, so there is no need for synchronized.

However, as soon as you access that ArrayList from within a worker thread, you WILL need to synchronize every single access to it.

like image 32
EboMike Avatar answered Sep 28 '22 03:09

EboMike