带有类 Reentrant(true) lock 的 Lock 接口的工作方式是它使用BlockingQueue来存储想要获取锁的线程。以这种方式“先来,先出去”的线程-FIFO。都清楚这一点。
但是“不公平锁”到哪里去了,或者 ReentrantLock(false)。他们的内部实现是什么?操作系统如何决定现在选择哪个线程?最重要的是现在这些线程还存储在队列中还是在哪里?(他们一定在某个地方)
假设您有以下代码:
public int getSpeedX() {
speedLock.lock();
try {
return speedX;
} finally {
speedLock.unlock();
}
}
public void setSpeedX(int x) {
speedLock.lock();
try {
speedX = x;
} finally {
speedLock.unlock();
}
}
Run Code Online (Sandbox Code Playgroud)
返回速度X好吗?或应该是:
public int getSpeedX() {
int temp;
speedLock.lock();
try {
temp = speedX;
} finally {
speedLock.unlock();
}
return temp;
}
Run Code Online (Sandbox Code Playgroud)
哪个是对的?或者他们是等同的?
我很难理解ReentrantLock.lock()的行为
我有以下课程
import java.util.concurrent.locks.*;
class BlockingClass {
private Lock lock = new ReentrantLock();
private Condition condition = lock.newCondition();
public void a() {
lock.lock();
System.out.println("called in method a(): lock()");
try {
System.out.println("called in method a(): await()");
condition.await();
}
catch (InterruptedException e) {}
finally {
lock.unlock();
System.out.println("called in method a(): unlock() ");
}
}
public void b() {
lock.lock();
System.out.println("called in method b(): lock()");
System.out.println("called in method b(): signalAll()");
condition.signalAll();
lock.unlock();
System.out.println("called in method b(): unlock() ");
}
}
Run Code Online (Sandbox Code Playgroud)
我运行以下测试:
class BlockingClassTest …Run Code Online (Sandbox Code Playgroud) 我被要求执行一个名为"ping"和"pong"的pingpong游戏(意思是ping之前没有乒乓)10次.意思是,控制台中的最终输出应该是:"ping!(1)","pong!(1)","ping!(2)","pong!(2)"等.
需求是使用信号量,reetrantlock和倒计时锁存器实现gamepingpongthread.
我的问题是打印顺序并不总是如我所要求的那样,我想知道我做错了什么.
这是代码:
// Import the necessary Java synchronization and scheduling classes.
import java.util.concurrent.Semaphore;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.Condition;
/**
* @class PingPongRight
*
* @brief This class implements a Java program that creates two
* instances of the PlayPingPongThread and start these thread
* instances to correctly alternate printing "Ping" and "Pong",
* respectively, on the console display.
*/
public class PingPongRight
{
/**
* @class SimpleSemaphore
*
* @brief This class provides a simple counting semaphore …Run Code Online (Sandbox Code Playgroud) 对于特定的线程安全数据结构,我需要保护对中央数据结构(即字节数组)的访问.在这种情况下,我选择使用ReentrantLocks,因为它的公平性政策以及创建多个条件的高级功能.
并发的条件很复杂,如下所示:
在我最初的实现中,我选择实现两个嵌套锁,如下所示:
ReentrantLock lockFoo = new ReentrantLock(true);
ReentrantLock lockCentral = new ReentrantLock(true);
Condition centralCondition = lockCentral.newCondition();
public void foo(){
// thread-safe processing code here
lockFoo.lock();
lockCentral.lock();
try{
// accessing code here
try{
// waits upon some condition for access
while(someCondition){
centralCondition.await();
}
}catch(InterruptedException ex){
// handling code here
}
// more processing
}finally{
lockCentral.unlock();
lockFoo.unlock();
}
}
Run Code Online (Sandbox Code Playgroud)
结构在方法上是等效的bar,只需用另一个锁对象lockBar.此外,代码减少了我更复杂的多条件等待,并为简单起见信号到单一条件.
使用这个,我不禁感到代码看起来不必要地复杂和模糊不仅因为有两个嵌套的锁,它们共享一个try-finally,更不用说如何在整个过程中lockCentral释放和重新获取多次lockFoo.
相反,我试图重新组织外锁(lockFoo和lockBar)作为一个条件lockCentral,如下所示:
ReentrantLock lockCentral …Run Code Online (Sandbox Code Playgroud) 我有一个名为processOutbox的方法.我希望它是线程安全的.当一个线程在它时,我不希望另一个线程调用此方法.我已经按照以下方式实现了它.我做得对吗?我的实施有漏洞吗?如果有,请告知我如何解决它.
this.start();
outboxLock.lock();
timer = new Timer();
try{
timer.scheduleAtFixedRate(new TimerTask() {
public void run() {
processOutbox();
}
}, 0, period);
} finally{
outboxLock.unlock();
}
Run Code Online (Sandbox Code Playgroud) 我有一个主线程和一个工作线程。主线程将任务添加到队列中,工作线程将其用于计算数据。在将对象放入队列之前,我在任务对象内的ReentrantLock对象(在主线程上)上调用锁。当工作线程完成了从队列中处理任务的工作后,我称解锁(在工作线程上)。问题是我收到一个IllegalMonitorStateException,因为我在不同的线程上调用了锁定和解锁。
我正在寻找可以在不同线程上执行此操作的替代锁定系统。
例:
public class Worker extends Thread {
public static Queue<Task> tasks = new ConcurrentLinkedQueue<Task>();
@Override
public void run() {
while (true) {
Task task = tasks.poll();
if (task != null) {
task.work();
task.lock.unlock(); // Here is the unlock, Task#i should not change up to now
}
}
}
}
public class Task {
private int i = 0;
public Lock lock;
public void setI(int i) {
lock.lock();
this.i = i;
lock.unlock();
} …Run Code Online (Sandbox Code Playgroud) 我想弄清楚我们如何才能正确地等待另一个线程中的锁被释放。
我认为代码会更好地解释我的意思:
myLock.lock();
sendSomewhereMyLock(myLock); //creates new threads inside
myLock.waitUntilReleasedByAnotherThread(60L, TimeUnit.SECONDS);
//do something after the lock is released
Run Code Online (Sandbox Code Playgroud)
我认为这tryLock(long time, TimeUnit unit)是我需要的方法,但 Java 文档说该方法将立即执行,因为当前线程获取了锁:
如果锁可用,则此方法立即返回 true 值。如果锁不可用,则当前线程将出于线程调度目的而被禁用并处于休眠状态,直到发生以下三种情况之一:
- 锁被当前线程获取;或者
- 其他一些线程中断当前线程,支持中断获取锁;或者
- 经过指定的等待时间
那我应该用什么?
我已经在这里搜索过这个错误,但我认为我的代码看起来是正确的:
这是代码的摘录,如果我尝试运行代码,我会得到 java.lang.IllegalMonitorStateException:当前线程不是所有者。错误出在 cond.wait() 方法中。
public void takeARest() {
lock.lock();
try {
while (disembark < totalPassengers) {
System.err.printf("Held by %s%n",lock.isHeldByCurrentThread());
cond.wait();
}
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
Run Code Online (Sandbox Code Playgroud)
有任何想法吗?
我对高级 Java 和学习可重入锁相当陌生。我知道 ReentrantLock 有一个公平参数,它确保将锁提供给大多数饥饿的线程(与同步内部锁的情况不同。)
但是,Reentrant 也意味着同一个线程可以通过增加holdCount 一次又一次地重新获取锁。如果同一个线程永远获取锁,如何保证公平性?