我正在准备Java SE 7 Programmer II考试。在其中一个模拟考试中,有一个练习来描述代码遭受的线程问题。这是代码:
public class Test {
public static void main(String[] args) {
final Counter obj1 = new Counter("obj1");
final Counter obj2 = new Counter("obj2");
new Thread(new Runnable() {
@Override
public void run() {
Thread.currentThread().setName("first");
obj1.display(obj2);
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
Thread.currentThread().setName("second");
obj2.display(obj1);
}
}).start();
}
}
class Counter extends Thread {
int i = 10;
String name;
public Counter(String name) {
this.name = name;
}
public synchronized void display(Counter obj) {
try {
Thread.sleep(5);
obj.increment(this);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public synchronized void increment(Counter obj) {
System.out.println(++i);
}
}
他们说这是一个活锁。我看不到。有人可以更详细地解释一下。
答案 0 :(得分:3)
根据维基百科的定义,我不会将其视为 livelock
活锁类似于死锁,除了状态 活锁中涉及的过程不断变化 彼此没有进步。
虽然它确实符合死锁的定义
在操作系统中,死锁是指a时发生的情况 进程或线程因请求的资源而进入等待状态 正在等待另一个等待过程的等待过程 另一种资源。如果进程无法更改其状态 无限期地因为它所请求的资源正被使用 另一个等待过程,然后系统被认为陷入僵局。
你的第一个帖子锁定了obj1
,第二个锁定了obj2
,然后他们请求另一个锁定和阻止。
答案 1 :(得分:1)
检查线程状态后,我现在确定它是死锁!
我将线程存储在本地t1
和t2
中,以便调用getState()
方法。
启动线程后调用System.out.println(t*.getState())
,打印: TIMED_WAITING 。
在display
方法 AFTER Thread.sleep(5)
中相同,打印: RUNNABLE
现在关键部分:
再次在System.out.println(t*.getState())
中调用t1
(对于t2
和main
两个帖子),但这次sleep(5000)
将打印 BLOCKED
阻止意味着:等待获取锁定,这意味着它是 DEADLOCK!
答案 2 :(得分:0)
以下是每个线程的工作原理:
run
方法中发生,因为Counter.display
为synchronized
。display
方法。increment
方法,因为increment
方法为synchronized
。除了不设置i
volatile的问题,因为它可以以多线程方式访问,这里存在许多与锁相关的问题,但主要问题是:
在第1
阶段请求锁定之前,未释放步骤3
中的锁定。对我而言,这是一个潜在的死锁,因为如果两个线程都在其他命中1
之前通过阶段3
,则两个线程都会锁定。但是,由于两个线程实际上可以正常工作,只要它们从未击中它,然后可能可以将其解释为活锁,因为两个线程可以愉快地一起运行一段时间在他们最终致命拥抱之前。
所以我称之为潜在的僵局,并让小贩决定将其称为什么。
答案 3 :(得分:0)
超越程序并获得线程转储
第一个帖子
"first@573" prio=5 tid=0xb nid=NA waiting for monitor entry
java.lang.Thread.State: BLOCKED
blocks second@575
waiting for second@575 to release lock on <0x245> (a dp.Counter)
at dp.Counter.increment(LiveLock.java:44)
at dp.Counter.display(LiveLock.java:37)
- locked <0x246> (a dp.Counter)
at dp.LiveLock.lambda$main$0(LiveLock.java:15)
at dp.LiveLock$$Lambda$1.16460856.run(Unknown Source:-1)
at java.lang.Thread.run(Thread.java:745)
和第二个帖子
"second@575" prio=5 tid=0xc nid=NA waiting for monitor entry
java.lang.Thread.State: BLOCKED
blocks first@573
waiting for first@573 to release lock on <0x246> (a dp.Counter)
at dp.Counter.increment(LiveLock.java:44)
at dp.Counter.display(LiveLock.java:37)
- locked <0x245> (a dp.Counter)
at dp.LiveLock.lambda$main$1(LiveLock.java:20)
at dp.LiveLock$$Lambda$2.23661220.run(Unknown Source:-1)
at java.lang.Thread.run(Thread.java:745)
看起来像死锁情况。