4

I have a problem where I have a datastructure and multiple threads trying to do operations on it. To say it as simple as possible: I have thread A, B and C. Thread A can only do its operation, as long as B and C are not making any changes to the data set. B and C can operate simultaneously on the set most of the time though. So the goal is:

  • Thread A blocks B & C
  • Thread B & C block A
  • Thread B does NOT block C (and vice versa)

The question is, how can I achieve that? I hope it is clear what I am trying to do. If not, feel free to comment. I have deliberately not provided any code, as it is in my opinion easier to grasp the problem this way (a lot of long code).

ROMANIA_engineer
  • 54,432
  • 29
  • 203
  • 199
Kugelblitz
  • 582
  • 5
  • 24
  • Do you will allways have 3 Threads at the same time, or are multiple possible? @Phil – Timo Hanisch Apr 10 '15 at 12:42
  • 1
    @TimoH There will most of the times be more than 3 Threads. For example 1 Thread doing the A-operation, and 9 Threads doing the B or C operations. That means there will always be 1 Thread like A, which can only run if nothing else is running, but there can be an arbitrary number of other threads, which can run in parallel. – Kugelblitz Apr 10 '15 at 12:46
  • I guess you will need another class to act as a semaphore to help orchestrate when threads should process or not. – Sanj Apr 10 '15 at 12:50

3 Answers3

2

You can use ReentrantReadWriteLock

skozlov
  • 384
  • 1
  • 12
  • This makes sence to me if there are multiple readers and only one writer. In my case however, the multiple threads (B & C in the example) can WRITE (as long as the elements they are changing are different) simultaneously, but A is the reader, and can only read if no changes are being made by B and C. Does this ReentrantReadWriteLock also work with that concept? – Kugelblitz Apr 10 '15 at 12:54
  • 1
    @Phil it does not matter that your threads are actually performing read/write. The B,C will take the read lock (even if they do write operations) as it is not exclusive, and A takes write lock as this blocks any other access. – Zielu Apr 10 '15 at 12:56
  • @Phil, threads cannot know whether an operation is "read" or "write". – skozlov Apr 10 '15 at 13:01
  • @Zielu Thank you, in that case this will work just as I need it to! – Kugelblitz Apr 10 '15 at 13:02
  • @skozlov unless you add some more words (code) to your answer. It will be most likely deleted as LinkOnlyAnswer even if it is correct one and worked for the author. – Zielu Apr 10 '15 at 13:04
  • @Zielu Agreed, I would also add a little code example or something if I was you. If only even to help someone else, looking for this issue in the future. But thanks! EDIT: That's directed at skozlov, of course – Kugelblitz Apr 10 '15 at 13:07
2

You want to use Semaphore with 2 permits for that.

Your A thread will ask allways for two permits (acquire(2)).

Your B and C thread will ask only for one permit (acquire()).

That way B and C can always work toghether, A will block B or C (as no permists are available). B or C will block A as only one permit is left.

It will work for any known numbers of (B,C) threads as the semaphore can be set to this number. Main problem is the potential starvation of A if B and C will keep getting always one permit. So if N = nr(B)+nr(C), then any thread of type A requires(N). It will not work for unknown number of B,C as the semaphore permits number cannot be dynamically increased.

Zielu
  • 8,312
  • 4
  • 28
  • 41
  • I think this would be the correct solution if he would only use 3 threads, but I think this won't work if he has multiple threads doing the work of A and B + C – Timo Hanisch Apr 10 '15 at 12:55
  • It works as long as all the A threads require N permits where N = number of (B+C). It does not work if the numbers are not known beforehand. – Zielu Apr 10 '15 at 12:57
  • @Zielou Yep. But if he dynamically spawns threads it would become more complex I guess. For example. N = B + C = 2 , A tries to aquire the semaphore with N = 2, so aquire(2), Now D joins the ring, with the same permissions as B + C, so N = 3, but A tries to aquire the semaphore with N = 2. Hope It is clear – Timo Hanisch Apr 10 '15 at 13:00
  • @TimoH Thank you guys. This would work aswell, as I figure. I will probably try it aswell, for learning sake. I did however now use the ReentrantReadWriteLock, which worked fine, thanks a lot! – Kugelblitz Apr 10 '15 at 13:03
-1

You need to make your object thread safe.

In short you must :

  1. Make your fields private
  2. Find your criticals sections and protect them with synchronized bloc

in this page resume the concept very well and explain others approaches.

Once your field are correctly protected on Basic CRUD actions (Create, read, update, delete), you can make specific methods specialized in reading data for your threads B & C and others for Thread A

A. Ocannaille
  • 306
  • 4
  • 14
  • I don't quite understand what you mean in your last half of the last sentence. The rest is clear to me, that's not the big problem, thanks. – Kugelblitz Apr 10 '15 at 12:51