换句话说,我不希望线程在无法访问锁时等待(如在同步中),我希望线程执行在无法获得锁时立即立即返回。
像这样简单的 boolean 锁可能会允许多个线程访问。
private static boolean lockAvailable = true;
private boolean acquireLock() {
if(lockAvailable) {
lockAvailable = false;
return true;
}
return false;
}
我错过了什么吗?实现此目标的最佳/最简单方法是什么?
编辑:
感谢您指出信号量 (!)
所以再看一遍这段代码是防弹的?
private final static Semaphore lock = new Semaphore(1, true);
public void tryAndDoSomething() {
if(lock.tryAcquire()) {
try {
// only single thread can access here at one time
} finally {
lock.release();
}
}
}
更新:
我意识到我需要可重入功能,所以我创建了一个简单的非阻塞可重入功能。为任何对您如何执行此操作感兴趣的人发布代码。任何想要这种功能的人当然应该使用 existing Java 类 java.util.concurrent.locks.ReentrantLock :|
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
/**
* SimpleNonBlockingLock ensures that only a single thread can call protected code at any one time,
* while allowing other threads to by pass the protected code if the lock is unavailable.
* The thread owning the lock can access any code protected by the lock (the lock is 'reentrant').
* To function correctly the protected code must be executed in a try/finally blocks. The
* finally block must call the tryRelease. Example code:
*
* private final SimpleNonBlockingLock lock = new SimpleNonBlockingLock();
*
* if(lock.tryAcquire()) {
* try {
* // access protected code
* } finally {
* lock.tryRelease();
* }
* }
*
* This code is for demonstration only and should not be used. I have tested it and it 'seems to' work.
* However it may contain horrific bugs!
*
* The Java class java.util.concurrent.locks.ReentrantLock has been around since Java 5.0 and contains all (and more)
* of this functionality. Its also been thoroughly tested!
*/
public class SimpleNonBlockingLock {
// Atomic locking mechanism
private final AtomicBoolean locked = new AtomicBoolean();
// Atomic integer containing the next thread ID to be assigned
private static final AtomicInteger nextId = new AtomicInteger(0);
// Unique ID of thread which currently has lock
private int threadUniqueId = -1;
// Tracks number of tryAcquire calls made by thread with lock
private int lockCount = 0;
// Thread local variable containing each thread's ID
private static final ThreadLocal<Integer> threadId = new ThreadLocal<Integer>() {
@Override protected Integer initialValue() {
return nextId.getAndIncrement();
}
};
public synchronized boolean tryAcquire() {
// Allow owning thread to acquire
if(threadUniqueId == getCurrentThreadUniqueId()) {
lockCount++;
return true;
}
// If locked then do not allow
if (locked.get()) {return false;}
// Attempt to acquire lock
boolean attemptAcquire = locked.compareAndSet(false, true);
// If successful then set threadUniqueId for the thread, and increment lock count
if(attemptAcquire) {
threadUniqueId = getCurrentThreadUniqueId();
lockCount++;
}
// Return result of attempt to acquire lock
return attemptAcquire;
}
public synchronized boolean tryRelease() {
if (!locked.get()) {
// Lock is currently available - no need to try and release
return true;
} else {
// Decrement the lock count
lockCount--;
// If lock count is zero we release lock, and reset the threadUniqueId
if(lockCount == 0) {
threadUniqueId = -1;
return locked.compareAndSet(true, false);
}
return false;
}
}
// Returns the current thread's unique ID, assigning it if necessary
public static int getCurrentThreadUniqueId() {
return threadId.get();
}
}
最佳答案
Java 5 引入了 explicit locks有一个 tryLock
手术。所以使用显式锁而不是同步块(synchronized block),然后你可以调用tryLock
:
private Lock lock = ...;
private boolean acquireLock() {
if (lock.tryLock()) {
...
return true;
} else {
return false;
}
}
关于java - 简单的 Java 代码允许单线程访问和其他线程跳过/继续,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7359005/