简体   繁体   English

我可以让线程等待锁,然后在释放后跳过它吗?

[英]Can I make threads wait for a lock and then jump over it once released?

Given is the following pseudo code.给出了以下伪代码。 A function may be entered by multiple threads simultaneously.一个 function 可以由多个线程同时进入。 I want all threads to execute a() and c() , but b() must only be executed by those threads that were not locked when entering the synchronized block.我希望所有线程都执行a()c() ,但是b()只能由进入同步块时未锁定的那些线程执行。

In other words: If a thread must wait for the lock, then I want it to wait until the lock is released and then jump over b() and continue with c() right away.换句话说:如果一个线程必须等待锁,那么我希望它等到锁被释放,然后跳过b()并立即继续c()

    public void code() {
        a() // check if page is present locally

        if (pageMissing) {
            synchronized (this) {
                page = b(); // get page over REST
            }
        }

        c() // access page
    }

How is this useful?这有什么用? Imagine b() calls an external REST function to update local data.想象一下b()调用外部 REST function 来更新本地数据。 When a thread enters, we want to be sure that the function is called and local data is updated, but once the blocking thread exits b() we know local data is current and we don't want to waste resources in having consecutive threads that were already waiting call the update function again.当一个线程进入时,我们希望确保调用 function 并更新本地数据,但是一旦阻塞线程退出b()我们知道本地数据是最新的,我们不想浪费资源让连续线程已经在等待再次调用更新 function。

You can have a boolean flag (instance variable) that denotes whether b() has been called or not.您可以有一个boolean标志(实例变量),表示是否已调用b() All threads that enter the synchronized block will check this condition before calling b() .所有进入同步块的线程都会在调用b()之前检查这个条件。

private boolean isDone = false;

public void code() {
    a();
    synchronized (this) {
        if (!isDone) {
            b();
            isDone = true;
        }
    }
    c();
}

Only the first thread that acquires the lock will call b() .只有第一个获得锁的线程才会调用b() After it succeeds, it will set the flag to true and will exit the block.成功后,它将标志设置为 true 并退出该块。 All subsequent threads entering the block will fail on the if condition and hence will not invoke b() .进入块的所有后续线程都将在if条件下失败,因此不会调用b()


If you do not want the other threads to wait on the synchronized block's lock and want to continue to call c() , you can remove the synchronized keyword and use an AtomicBoolean and use its compareAndSet如果您不希望其他线程等待同步块的锁并希望继续调用c() ,则可以删除 synchronized 关键字并使用AtomicBoolean并使用其compareAndSet

 private AtomicBoolean isDone = new AtomicBoolean(false);

 public void code() {
    a();
    if (isDone.compareAndSet(false, true)) {
       b();
    }
    c();
}

Javadoc of compareAndSet states compareAndSet状态的 Javadoc

Atomically sets the value to the given updated value if the current value {@code ==} the expected value.如果当前值 {@code ==} 是预期值,则自动将值设置为给定的更新值。

@return {@code true} if successful. @return {@code true} 如果成功。 False return indicates that the actual value was not equal to the expected value. False return 表示实际值不等于预期值。

So, the first thread that calls compareAndSet while isDone is false will succeed.因此,在isDone为 false 时调用compareAndSet的第一个线程将成功。 The others will get false as the return value and hence won't enter the block and can thus continue.其他的将得到false作为返回值,因此不会进入块,因此可以继续。


UPDATE: From your comments更新:根据您的评论

@user7 Yes, I am concerned with threads calling b() unnecessarily, but (see my other comment) I need those threads that arrive while b() runs to wait until it is finished before they continue with c() @user7 是的,我担心不必要地调用 b() 的线程,但是(请参阅我的其他评论)我需要那些在 b() 运行时到达的线程等到它完成后再继续 c()

Seems you need the first solution of mine.看来你需要我的第一个解决方案。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何让正在读取的行等待直到使用 JDBC 和 MySQL 释放锁定? - How can I make a row being read wait until a lock on it is released using JDBC and MySQL? 两个线程死锁但看不到原因,用notifyAll()释放锁 - Two threads deadlocking but can't see why, lock released with notifyAll() 我怎样才能让我的 Jump Animation 同时工作? - How Can I Make My Jump Animation Work All At Once? 多个线程可以同时在一个对象上等待吗? - Can multiple threads wait on one object at once? 如何使用等待/通知使这些线程交替工作? - How can I use wait/notify to make these threads work alternatively? Spring Data:如何在一个事务中锁定一行并使其他事务等待其释放? - Spring Data: How to lock a row in a transaction and make other transactions wait until it is released? 调用wait()方法后释放的锁? - Lock released after calling wait() method? 释放锁定后,监视器的“条目”集中的线程会怎样? - What happens to threads in the Entry set of a monitor when the lock is released? ActiveMQ 5.9-由于未释放锁定,代理上的线程被阻塞 - ActiveMQ 5.9 - BLOCKED threads on broker due to lock not released 如何确保方法只被多个线程调用一次? - How can I make sure a method is only called once by multiple threads?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM