Java 重入锁:第二个线程无法锁定



我刚刚开始在Java中使用同步方法,我已经制作了一个使用可重入锁的基本应用程序

这就是它应该做的:一个线程将首先通过锁定来访问被锁定的类,以防止冲突。一旦第一个线程完成了递增,那么第二个线程也将执行同样的操作。

我的问题是,在解锁后,第一个线程表示它已经解锁,而第二个线程仍将收到锁定状态,这意味着它处于饥饿状态。

这是我的代码

主类

public class JavaApplication3 {
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
// TODO code application logic here
SynchronizedInt s = new SynchronizedInt();
Thread t1 = new Thread(new FlameThread(s));
Thread t2 = new Thread(new FlameThread(s));
t1.start();
t2.start();
}
}

锁定类

public class SynchronizedInt {
private int count;
private Lock l;
public SynchronizedInt() {
this.count = 0;
this.l = new ReentrantLock();
}
public synchronized void addCounter() {
this.count++;
ThreadMessage.print(Integer.toString(this.count));
}
public synchronized Lock getLock() {
return l;
}
}

线程级

public class FlameThread implements Runnable {
private SynchronizedInt s;
public FlameThread(SynchronizedInt s) {
this.s = s;
}
@Override
public void run() {
while(true){
try {
try{
while(!this.s.getLock().tryLock()){
ThreadMessage.print(""+this.s.getLock().tryLock());
Thread.sleep(1000);
}
this.s.getLock().lock();
this.s.addCounter();
}finally{
this.s.getLock().unlock();
}
ThreadMessage.print(""+this.s.getLock().tryLock());
Thread.sleep(1000);
} catch (InterruptedException ex) {
Logger.getLogger(FlameThread.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}

线程消息

public class ThreadMessage {
// Display a message, preceded by
// the name of the current thread
public static void print(String message) {
String threadName = Thread.currentThread().getName();
System.out.format("%s: %s%n", threadName, message);
}
}

结果

run:
Thread-0: 1
Thread-0: true
Thread-1: false
Thread-0: 2
Thread-1: false
Thread-0: true
Thread-0: 3
Thread-1: false
Thread-0: true
Thread-0: 4
Thread-1: false
Thread-0: true

编辑#1:

预期输出

run:
Thread-0: 1
Thread-0: true
Thread-1: false
Thread-1: 2
Thread-1: true
Thread-0: false
Thread-0: 3
Thread-0: true
Thread-1: false
...

一个线程不应该占用所有的锁

编辑#2:

修复了问题。

显然,我不应该使用trylock。

您实际上是在threa.run中获取锁,使用lock和tryLock运行4次,并且只释放一次。更糟糕的是:你在释放它之后就重新锁定了它。这意味着在第一个线程完成之后,锁仍然是锁定的。

由于SynchronizedInt已经使用了synchronized关键字,因此您甚至不需要在此处锁定。此外,您甚至不需要synchronizedInt类,只需使用内置的AtomicInt即可。

最新更新