gpt4 book ai didi

java - lock.tryLock() 线程安全吗?

转载 作者:行者123 更新时间:2023-11-30 01:44:55 29 4
gpt4 key购买 nike

我尝试了使用同步、lock.lock()和lock.tryLock()的线程竞赛程序,我发现使用同步和lock.lock()工作得很好,但lock.tryLock()本身不是线程安全的。此方法无法获取锁,因此会产生意外结果


import java.util.concurrent.locks.ReentrantLock;

public class Main {
public static void main(String[] args) throws InterruptedException {

for (int i = 0; i < 10; i++) {


Resources resources = new Resources();
Thread userThread1 = new Increment(resources);
Thread userThread2 = new Decrement(resources);
userThread1.start();
userThread2.start();
userThread1.join();
userThread2.join();

System.out.println(resources.getCounter());
}
}

private static abstract class UserThread extends Thread {
protected Resources resources;

public UserThread(Resources resources) {
this.resources = resources;
}

}

private static class Increment extends UserThread {

public Increment(Resources resources) {
super(resources);
}

public void run() {
for (int i = 0; i < 10000; i++) {
resources.increemnt();

}

}
}

private static class Decrement extends UserThread {

public Decrement(Resources resources) {
super(resources);
}

public void run() {

for (int i = 0; i < 10000; i++) {
resources.decrement();

}

}
}

private static class Resources {

public ReentrantLock getLock() {
return lock;
}

private ReentrantLock lock = new ReentrantLock();

public int getCounter() {
return counter;
}

private int counter = 0;

public void increemnt() {
if (lock.tryLock()) {
try {
counter++;
} finally {
lock.unlock();
}

}
}

public void decrement() {
if (lock.tryLock()) {
try {
counter--;
} finally {
lock.unlock();
}

}
}
}

}

预期:0,0,0,0,0,0,0,0,0,0实际输出:每次运行都是随机的

最佳答案

tryLock 方法是线程安全的。它可靠地完成了它应该做的事情(根据 javadoc)。

但是,您使用trylock 的方式会导致incrementdecrement 实现非线程安全。如果您要在这种情况下使用 trylock,则需要执行以下操作:

try {
while (!lock.tryLock()) { } // Try to get the lock until you get it
counter++;
} finally {
lock.unlock();
}

但这不是一个好主意,因为您实际上正忙于等待锁。使用 Lock 的更好解决方案是:

try {
lock.lock(); // Block until the lock is acquired.
counter++;
} finally {
lock.unlock();
}

但是如果您追求无锁解决方案,那么您应该使用原子类型:

  • java.util.concurrent.atomic.LongAdder ( javadoc ) 对于 Java 8 及更高版本,
  • java.util.concurrent.atomic.AtomicLong ( javadoc ) 自 Java 5 以来的所有 Java 版本。

显然,如果存在大量争用,LongAdder 的性能会更好:

<小时/>

请注意,线程安全实际上是一个很难精确定义的概念。您需要从算法的正确行为的行为规范开始。然后你就可以说是该算法的一个实现。

Definition: When the algorithm is correct according to the specification when run on system with one processor, then it is thread-safe if it is also always correct according to the specification when there are multiple processors.

由此,我们看到:

  • 如果算法在单处理器情况下不满足其行为规范,那么线程安全就毫无意义,并且
  • 如果算法无法使用多个处理器,线程安全就毫无意义。

关于java - lock.tryLock() 线程安全吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58463597/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com