Multithreading – Understanding Event Ordering and Race Conditions

multithreading

Here's a scenario I need help with.

Say you have a dating app (distributed, multiple instances), that has a table likes

| id | user_id | liked_id |notification_sent|

If User A likes User B
    Insert into likes
    If likes contains (B likes A)
        Send match notification(A,B)
        Set notification_sent true for both rows 

Now, what happens if both users A and B like each other at the same time? (race condition)? there's a chance that the second if will be missed, as the rows are not inserted yet.

Solution A: Have a background service that runs periodically, checking for A likes B AND B likes A AND notification_sent=false

that's not really realtime

Solution B: Always retry the 2nd check, but that just seems wasteful.

Solution C: Lock the whole table! Nope!.

Is there any othert solution to force order of events/avoid the race condition?

Best Answer

From what I understand, the 2nd if condition is always supposed to be missed, since there must be a "User A likes User B" first (where the if condition will be missed) and then a "User B likes User A" (where the if condition is hit).

The only race condition I see that might be unwanted is when a thread yields to the other thread just after "Insert into likes". Which might cause the operation "Send match notification(A,B)" to run twice.

In your case you know then that "Send match notification(A,B)" will run at-least once.

Now, if you want to change this to a run only-once, then you have to create a lock on the "likes" tables on rows A likes B and B likes A.

If User A likes User B
    Insert into likes
    If likes contains (B likes A)
        Lock both rows
        if A likes B has notification_sent is false
            Send match notification(A,B)
            Set notification_sent true for both rows
        Unlock both rows

This will ensure that the notification is only sent only once.