如何解决Java:多线程安全问题:使用线程扩展和锁
当我使用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();
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。