java单个线程等待,Java-允许一个线程更新值,其他线程等待和跳过关键部分

Hi I have a situation in which I have to allow only one thread to say update a variable.

There is a trigger, which might invoke multiple threads to update this variable, however the update should happen only once by the first thread whichever arrives at the critical section.

Ideally the flow should be like follows:

Thread-1; Thread-2 and Thread-3 are invoked to update a variable in critical section guarded by a lock or a mutex

Critical section using this guard allows only one thread to enter, Thread-2 and Thread-3 wait just outside.

Once this variable is updated by Thread-1; Thread-2 and Thread-3 resume with other work without causing an effect on the variable.

I have come up with the following implementation, but I am not able to make other threads wait and skip updation:

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());

}

}

}

}

At the end, the counter value is 3, I want counter value to be one also I want other threads to wait till the first thread updates the counter. Ideas appreciated. I would prefer a solution using locks / mutex rather than wait and notify.

Output:

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

Note

My use case, is different - the example of updating a counter is for simplicity sake. Actually I am updating a session token in the doSomeOperation method.

解决方案

Problem is occurring because Initially one thread increases the counter and release the lock and your program is running so fast that, once first thread releases the lock then another thread enters the method and it sees the lock free so it acquires the lock and increase the counter further. You can make use of countDownLatch in this case.

Here one thread which get the lock decrease the latch count by one and makes it zero, after that none of the thread will be able to process because

latch.getCount()==1 condition will fail.

import java.util.concurrent.CountDownLatch;

import java.util.concurrent.locks.ReentrantLock;

public class Test2 {

private static ReentrantLock lock = new ReentrantLock();

private static CountDownLatch latch= new CountDownLatch(1);

private int counter = 0;

public static void main(String[] args) {

Test2 m = new Test2();

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() && latch.getCount()==1) {

System.out.println("Lock held by " + Thread.currentThread().getName() + " " + lock.isHeldByCurrentThread());

counter++;

latch.countDown();

Thread.sleep(3000);

System.out.println("Counter value: " + counter + " worked by thread " + Thread.currentThread().getName());

}

System.out.println("Exiting" + Thread.currentThread().getName());

} catch (Exception ex) {

ex.printStackTrace();

} finally {

if (lock.isHeldByCurrentThread()) {

lock.unlock();

System.out.println("Unlocked: " + Thread.currentThread().getName());

}

}

}

}

import java.util.concurrent.CountDownLatch;

import java.util.concurrent.locks.ReentrantLock;

public class Test2 {

private static ReentrantLock lock = new ReentrantLock();

private static CountDownLatch latch= new CountDownLatch(1);

private int counter = 0;

public static void main(String[] args) {

Test2 m = new Test2();

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() && latch.getCount()==1) {

System.out.println("Lock held by " + Thread.currentThread().getName() + " " + lock.isHeldByCurrentThread());

counter++;

latch.countDown();

Thread.sleep(3000);

System.out.println("Counter value: " + counter + " worked by thread " + Thread.currentThread().getName());

}

System.out.println("Exiting" + Thread.currentThread().getName());

} catch (Exception ex) {

ex.printStackTrace();

} finally {

if (lock.isHeldByCurrentThread()) {

lock.unlock();

System.out.println("Unlocked: " + Thread.currentThread().getName());

}

}

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值