- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我尝试了使用同步、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
的方式会导致increment
和decrement
实现非线程安全。如果您要在这种情况下使用 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/
我是一名优秀的程序员,十分优秀!