问题描述
当我使用Thread类和Lock来解决线程安全问题时,出现0票!
代码:
package ThreadTest;
import java.util.concurrent.locks.reentrantlock;
class ThreadOne extends Thread{
private static int ticket = 100;
private reentrantlock lock = new reentrantlock();
@Override
public void run() {
while(true){
try {
lock.lock();
if(ticket > 0){
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printstacktrace();
}
System.out.println(Thread.currentThread().getName()+"selling ticket: "+ticket);
ticket--;
}else{
break;
}
} finally {
lock.unlock();
}
}
}
}
public class ThreadMethod {
public static void main(String[] args) {
ThreadOne t1 = new ThreadOne();
ThreadOne t2 = new ThreadOne();
t1.setName("Window 1:");
t2.setName("Window 2:");
t1.start();
t2.start();
}
}
结果包含: 窗口2:售票:3 窗口1:售票:2 窗口2:售票:1 窗口1:售票:0
0 票!
解决方法
第一个问题是每个 ThreadOne
实例都有两个独立锁,所以实际上并没有锁定任何东西。甚至尝试获取线程之间的锁都没有竞争,因为它们都有自己的锁。如果您使 ReentrantLock
static
,这很容易解决。
如果您确实做到了 static
,您会注意到只有一个“窗口”会继续获得门票。这与 ReentrantLock
内部的工作方式以及您使用的是 while(true){...}
的事实有关。这也很容易修复。要么:
-
将锁更改为公平:
private static ReentrantLock LOCK = new ReentrantLock(true);
-
或者在 finally 块之后休眠一点,让另一个线程有机会运行。
像这样:
.....
} finally {
LOCK.unlock();
}
try {
Thread.sleep(10);
}
catch (InterruptedException e) {
e.printStackTrace();
}