Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
151 views
in Technique[技术] by (71.8m points)

java - How to make sure two actions are never executed by different threads at the same time?

Let's assume I have two functions, doAction1() and doAction2().

Both of those functions can be executed by multiple threads.

Multiple, concurrent activations of doAction1() are allowed, and multiple concurrent activations of doAction2() are allowed, but I do not want to allow any activation of doAction1() to overlap an activation of doAction2(). In other words, if any thread want to execute doAction1(), it should wait until all current executions of doAction2() are finished, and other way around.

If I just wanted doAction2() always to be executed after doAction1(), I could use something like Phaser. Is there something like Phaser with dependencies in both directions? Getting stuck in executing one action all the time is not a concern.

I believe I could have something like thread counters on both actions and have a logic to wait until no threads with other action are active, but I do not like this solution.

I do not have much experience with multithreading, can someone here help?

question from:https://stackoverflow.com/questions/66068120/how-to-make-sure-two-actions-are-never-executed-by-different-threads-at-the-same

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Well, doAction2 needs to set a lockdown condition which doAction2 itself doesn't need, but which freezes any doAction1 calls.

This is considerably more complicated than it initially sounds because you're set up for a race condition.

Here is one strategy, using primitive operations:

private final Object locker = new Object();
private int a1 = 0, a2 = 0;

public void doAction1() {
    synchronized (locker) {
       //one central lock to avoid race conditions.
       while (a1 > 0) locker.wait();
       a2++;
    }
    
    try {
        doAction1ForReal();
    } finally {
        synchronized (locker) {
            a2--;
            locker.notifyAll();
        }
    }
}

and the same for dA2. You can use Lock objects from j.u.c of course, but not sure how it would end up any cleaner - you want guarantees that you can't deadlock (where a1 and a2 are both non-0, that'd be a deadlock here). Pretty sure this take cannot possibly result in deadlock: a2 cannot possibly be incremented until a1 is 0.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...