0

I have three services in my Android app that are fired by two broadcast receivers. The first two write onto a file and are fired by one broadcast receiver so I can make sure that they are executed one after the other (via Context.sendOrderedBroadcast()). The third one is on its own and is fired by a separate broadcast receiver, but reads from the same file that the first two write on.

Because the broadcast receivers may be fired at the same time or nearly the same time as each other, the file might also be accessed concurrently. How can I prevent that from happening? I want to be able to either read first then write or write then read. I'm just not sure if this problem is similar to Java concurrency in general because android services, if I'm not mistaken, are an entirely different beast.

Matthew Quiros
  • 13,385
  • 12
  • 87
  • 132

3 Answers3

0

One solution would be to have your writing tasks create an empty temporary file (say .lock) before accessing the shared file and delete that same temporary file once they are done.

Your reading task can check whether .lock file exists or not.

Alternatively, you can use a FileLock.

assylias
  • 321,522
  • 82
  • 660
  • 783
  • I'm not so sure any of the two is a good solution. 1) The creation of the `.lock` file might take more time than the Services themselves being able to access the file already. 2) I just tried that out, and apparently it's not going to work: http://stackoverflow.com/questions/12616975/how-to-start-concurrent-threads-that-acquire-a-file-lock-and-wait-on-each-other – Matthew Quiros Sep 27 '12 at 09:14
  • @mattquiros Thanks for the feedback - don't hesitate to add your own answer (and accept it) if you find a better way of doing that. – assylias Sep 27 '12 at 09:24
  • Unfortunately I haven't yet, although I've been told to take a look at `ReentrantLock`. Something similar to your suggestion but reusable with other threads. – Matthew Quiros Sep 27 '12 at 09:31
0

http://developer.android.com/reference/android/app/Service.html Note that services, like other application objects, run in the main thread of their hosting process. This means that, if your service is going to do any CPU intensive (such as MP3 playback) or blocking (such as networking) operations, it should spawn its own thread in which to do that work.

I suggest to read from/write to file in separate thread. You can use Only one thread at a time! for doing it in the same thread.

Community
  • 1
  • 1
Taras Shevchuk
  • 331
  • 2
  • 12
  • 1
    If I spawn a separate thread within the service to perform those tasks (actually, I'm thinking more of an `AsyncTask`), wouldn't I lose control of the back-to-back execution of my first two services even if I used `sendOrderedBroadcast()`? That is, because those two services have separate threads inside of them, I won't be able to execute the two services one after the other anymore. – Matthew Quiros Sep 17 '12 at 09:09
0

First of all, I shouldn't have done the file I/O in the main UI thread which is the case with Services. It should be done in another thread, like an AsyncTask.

Secondly, the ReentrantLock method is so much easier. When locked, it tells the other threads accessing the same resource to wait, and proceed only when the lock has been released. Simply instantiate a new ReentrantLock() and share that lock among the methods that read to or write from the file. It's as easy as calling lock() and unlock() on the ReentrantLock as you need it.

Matthew Quiros
  • 13,385
  • 12
  • 87
  • 132