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

3

5

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?

Docila answered 4/3, 2011 at 18:58 Comment(0)
C
11

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.

Cosetta answered 4/3, 2011 at 19:37 Comment(3)
It's times like these that I'd love to be able to mark multiple answers as the correct one. This is a great explanation as well.Docila
Also, this explains why I did not need a Looper for my particular example (the Handler belonged to the "main" thread of the Activity, which already has a looper). The clock's running thread used the main activity's handler.post(runnable); method. Thanks again for the illuminating explanation.Docila
btw, I checked and MessageQueue is indeed synchronized.Perforated
M
3

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.

Microcopy answered 4/3, 2011 at 19:8 Comment(1)
Spot on about the event handler... in fact the clock itself is the event dispatcher, notifying interested parties about things such as "the alarm went off" or "it's midnight" or even "time has passed, here's my new time". Those events are indeed acted on in the UI thread while the running of the clock (and therefore the dispatching of the events) happens in the clock's running thread. It's also interesting that you mention ArrayLists as I've got an ArrayList containing all the event handler objects, which very well can be accessed by both the clock's running thread and the UI thread.Docila
S
1

Synchronized, wait and notify are low level concurrency constructs on top of which high level concurrency constructs like semaphores, blocking queues, barriers and Looper/Handler are implemented.

Most of what you see in java.util.concurrent (which implements high level concurrency patterns/constructs) is implemented on top of synchronized, wait and notify (if you ignore the lock free algorithms)

Looper/Handler mechanism in basically a lightweight implementation of producer-consumer pattern where you have one consumer but multiple producers. It was created to easily exchange messages between the UI thread and non UI threads. UI thread in android runs as a single threaded loop (i.e single consumer) but can take in updates from multiple non UI threads (i.e multiple producers via handlers).

Snapshot answered 14/2, 2013 at 14:28 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.