【发布时间】:2020-01-29 13:06:09
【问题描述】:
您好,我有一种情况,我必须只允许一个线程说更新变量。
有一个触发器,它可能调用多个线程来更新这个变量,但是更新应该只由第一个线程发生一次,以到达临界区为准。
理想情况下,流程应如下所示:
线程-1;调用 Thread-2 和 Thread-3 来更新由锁或互斥锁保护的临界区中的变量
使用此保护的关键部分只允许一个线程进入,线程 2 和线程 3 就在外面等待。
一旦这个变量被 Thread-1 更新; Thread-2 和 Thread-3 继续进行其他工作,而不会对变量造成影响。
我想出了以下实现,但我无法让其他线程等待并跳过更新:
public class Main {
private static ReentrantLock lock = new ReentrantLock();
private int counter = 0;
public static void main(String[] args) {
Main m = new Main();
new Thread(m::doSomeOperation).start();
new Thread(m::doSomeOperation).start();
new Thread(m::doSomeOperation).start();
}
private void doSomeOperation() {
try {
System.out.println("Thread about to acquire lock: " + Thread.currentThread().getName());
if (lock.tryLock()) {
System.out.println("Lock held by " + Thread.currentThread().getName() + " " + lock.isHeldByCurrentThread());
counter++;
// Thread.sleep(3000);
System.out.println("Counter value: " + counter + " worked by thread " + Thread.currentThread().getName());
}
} catch (Exception ex) {
ex.printStackTrace();
} finally {
if (lock.isHeldByCurrentThread()) {
lock.unlock();
System.out.println("Unlocked: " + Thread.currentThread().getName());
}
}
}
}
最后,计数器值为 3,我希望计数器值为 1,我希望其他线程等到第一个线程更新计数器。想法赞赏。我更喜欢使用锁/互斥锁而不是等待和通知的解决方案。
输出:
Thread about to acquire lock: Thread-0
Lock held by Thread-0 true
Thread about to acquire lock: Thread-1
Counter value: 1 worked by thread Thread-0
Unlocked: Thread-0
Thread about to acquire lock: Thread-2
Lock held by Thread-2 true
Counter value: 2 worked by thread Thread-2
Unlocked: Thread-2
Process finished with exit code 0
注意 我的用例不同——更新计数器的例子是为了简单起见。实际上我正在更新 doSomeOperation 方法中的会话令牌。
【问题讨论】:
-
if (lock.tryLock()) { counter++; }. -
如果我使用 if(lock.tryLock)
Thread about to acquire lock: Thread-0 Lock held by Thread-0 true Thread about to acquire lock: Thread-1 Counter value: 1 worked by thread Thread-0 Unlocked: Thread-1 Unlocked: Thread-0 Thread about to acquire lock: Thread-2 Lock held by Thread-2 true Counter value: 2 worked by thread Thread-2 Unlocked: Thread-2我有以下输出 -
计数器似乎更新了两次 - 仍然。
-
你想要一个变量来检查是否有东西已经进入了临界区。
-
我不能依赖一个变量,这个操作可能需要稍后再做一次,在这种情况下这个变量将不允许由一组新的线程进行更新。否则我将不得不承担多次创建此类的开销。
标签: java multithreading locking mutex semaphore