下面的代码允许我们运行一段job时间,确保一次只能运行一个作业ReentrantLock.
有没有办法修改此代码以job.call()异步运行并MyConcurrentJobException在启动线程之前返回到客户端?
我们试图包裹的try/catch /终于在一个新的块Thread,但unlock与lock在同一线程的情况发生,所以我们得到一个IllegalMonitorException
??
final static Lock lock = new ReentrantLock();
public Object runJob(String desc, Callable job, boolean wait) {
logger.info("Acquiring lock");
if (!lock.tryLock()) {
throw new MyConcurrentJobException();
}
activeJob = new JobStatus(desc);
logger.info("Lock acquired");
try {
return job.call();
} catch (MarginServiceAssertionException e) {
throw e;
} catch (MarginServiceSystemException e) {
throw e;
} catch (Exception e) {
throw new MarginServiceSystemException(e);
} finally { …Run Code Online (Sandbox Code Playgroud) 以下是典型的读写器模式(大量读取和少量写入)
private ReadWriteLock lock = new ReentrantReadWriteLock();
private int value;
public void writeValue(int newValue){
lock.writeLock().lock();
try{
this.value = newValue;
}
finally{
lock.writeLock().unlock();
}
}
public int readValue(){
lock.readLock().lock();
try{
return value;
}
finally{
lock.writeLock().unlock();
}
}
Run Code Online (Sandbox Code Playgroud)
我想知道是否有可能优先考虑作家和读者?例如,通常编写者可能会等待很长时间(可能永远),如果其他线程持有读取锁定,那么是否可以让编写器具有更高的优先级,因此每当编写器出现时,它都可以被认为是正如高优先级(跳过线)类似的东西.
java multithreading reentrantreadwritelock readwritelock reentrantlock
我从这个API中采取了以下几点,我想知道以下两点之间的区别:
等待线程以FIFO顺序发出信号.
从等待方法返回的线程的锁重新获取的顺序与最初获取锁的线程的顺序相同,这是在未指定的默认情况下,但是对于公平锁,有利于那些等待时间最长的线程.
它与Condition通常由ReentrantLock方法返回的类有关,.newCondition()我引用它的位解释Condition了Object类的方法和常规监视方法之间的区别.
"等待线程以FIFO顺序发出信号".我认为,只要lock创建了a 或者是否公平,等待线程以FIFO顺序发出信号的事实完全无关紧要不是吗?因为无论如何,它们是否已经构建,公平与否,这决定了它们如何排队.
只是要求确认.
提前致谢.
我们知道,ReentrantLock有一个最大的重入限制:Integer.MAX_VALUE; synchronized块是否也有重入限制?
更新:我发现很难为同步重入编写测试代码:
public class SyncReentry {
public static void main(String[] args) {
synchronized (SyncReentry.class) {
synchronized (SyncReentry.class) {
// ...write synchronized block for ever
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
任何人都可以帮助编写一些同步重入限制测试的代码吗?
我正在尝试编写一个测试,在其中我想演示公平和不公平可重入锁之间的区别。该测试使用ThreadPoolExecutor并由多个迭代组成,每个迭代都有以下步骤:
AtomicInteger状态。因此,对于公平锁,共享状态的最终值必须等于最后一个任务的索引。但测试在所有执行中约有 50% 失败。
我的代码如下所示:
@Test
void should_be_fair() throws InterruptedException, ExecutionException {
int iterationsCount = 100;
int waitingThreadsCount = 5;
ReentrantLock lock = new ReentrantLock(true);
Semaphore unlockingSemaphore = new Semaphore(1);
boolean wasAnyThreadUnfair = false;
for (int i = 0; i < iterationsCount; i++) {
unlockingSemaphore.acquire();
ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors.newFixedThreadPool(waitingThreadsCount + 1);
Future<?> lockingFuture = executor.submit(() -> {
try {
lock.lock();
unlockingSemaphore.acquire();
} catch (InterruptedException e) {
throw new …Run Code Online (Sandbox Code Playgroud) 我知道如果使用ReentrantLock,它允许同一个线程多次获取相同的锁.在内部,它有一个计数器来计算锁定采集的数量.如果您两次获得相同的锁定,则需要将其释放两次.但我的问题是,如果有一次获得足够的话,为什么有人想多次获得锁?有人可以给我一个常见的用例吗?
我正在使用ReentrantLock及其推荐的做法(锁定,然后将实际代码放入try-block中,然后最后进行解锁,请参见下面的代码示例)。有时(非常罕见)我在解锁期间遇到java.lang.IllegalMonitorStateException异常。为什么会发生?也许它与Android的Java VM实现有关。
错误:
java.lang.IllegalMonitorStateException
java.lang.IllegalMonitorStateException
at java.util.concurrent.locks.ReentrantLock$Sync.tryRelease(ReentrantLock.java:126)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.release(AbstractQueuedSynchronizer.java:1232)
at java.util.concurrent.locks.ReentrantLock.unlock(ReentrantLock.java:430)
at com.example.dummy.backend.model.Model.unlock(Model.java:283)
at com.example.dummy.backend.engine.Engine.removeOldInstances(Engine.java:712)
at com.example.dummy.backend.engine.Engine$ProcessOnResumeWorkInBackground.doInBackground(Engine.java:836)
at com.example.dummy.backend.engine.Engine$ProcessOnResumeWorkInBackground.doInBackground(Engine.java:790)
at android.os.AsyncTask$2.call(AsyncTask.java:185)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:306)
at java.util.concurrent.FutureTask.run(FutureTask.java:138)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1088)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:581)
at java.lang.Thread.run(Thread.java:1019)
Run Code Online (Sandbox Code Playgroud)
代码示例(略有简化):
myLock.lock();
try {
LinkedList<MyClass> myClassInstances = model.getMyClassInstances();
Iterator<MyClass> iterator = myClassInstances.iterator();
while (iterator.hasNext()) {
MyClass myClassInstance = iterator.next();
boolean toBeRemoved = true; // simple condition here
if (toBeRemoved) {
logger.info("Removing old myClassInstance " + myClassInstance.getTimestamp());
iterator.remove();
Cache.removeMyClassByCodeAndTimestamp(myClassInstance);
}
}
} finally {
myLock.unlock();
}
Run Code Online (Sandbox Code Playgroud) 我遇到了一个声称是线程安全的Java类的例子.任何人都可以解释它是如何线程安全的?我可以清楚地看到类中的最后一个方法没有防止任何读者线程的并发访问.或者,我在这里错过了一些东西吗?
public class Account {
private Lock lock = new ReentrantLock();
private int value = 0;
public void increment() {
lock.lock();
value++;
lock.unlock();
}
public void decrement() {
lock.lock();
value--;
lock.unlock();
}
public int getValue() {
return value;
}
}
Run Code Online (Sandbox Code Playgroud) 我不明白他们之间的区别.我认为来自锁定界面的锁也是可重入的,那么它们之间的区别是什么?你什么时候用?
java concurrency multithreading java.util.concurrent reentrantlock
我有一些我认为非常简单的代码:
public int internalWrite(byte[] data, int offset, int size) throws InterruptedException {
lock.lockInterruptibly();
try {
if (state == State.RELEASED) throw new TrackReleasedException();
return track.write(data, offset, size, AudioTrack.WRITE_NON_BLOCKING);
} finally {
if (!lock.isHeldByCurrentThread()) {
Log.e("phonographnative", "internalWrite() lock is not held by current thread! " + Thread.currentThread());
} else lock.unlock();
}
}
Run Code Online (Sandbox Code Playgroud)
这lock是一个fairReentrantLock,但问题也会发生在非 ReentrantLock 上fair。track是一个Android AudioTrack;它的write方法主要是本机代码(但与线程无关)。它lock无论如何都无法访问。在实践中几乎从未抛出异常(并且在调查此行为时也从未抛出)。发生的情况是,非常可重现(稍后会详细介绍),锁将在同一线程内神秘地解锁,从而导致出现日志消息。以前,当我没有进行此检查时,预计会抛出 IllegalMonitorStateException。在这种情况发生了几次之后,java.lang.AssertionError: Attempt to repark锁的代码中就会有一个, 。一些示例性日志输出:
2019-03-20 12:20:37.428 8097-8181/com.kabouzeid.gramophone.debug E/phonographnative: internalWrite() lock is …Run Code Online (Sandbox Code Playgroud)