为什么这个代码不会死锁?
我正在调查setText上的死锁问题,但我需要先了解和了解有关死锁的信息。为此,我创建了一个简短的程序来尝试复制更大范围内可能发生的情况,但我不确定为什么我的小程序不会死锁。为什么这个代码不会死锁?
这里是我的学习计划:
public static void main(String[] a)
{
JFrame frame = new JFrame();
final JTextField p = new JTextField("start");
JButton btn = new JButton("button");
btn.addActionListener(new ActionListener()
{
@Override
public void actionPerformed(ActionEvent e)
{
SwingUtilities.invokeLater(new Runnable(){
@Override
public void run(){
p.setText(String.valueOf(System.nanoTime()));
}
});
}
});
frame.getContentPane().setLayout(new FlowLayout());
frame.getContentPane().add(p);
frame.getContentPane().add(btn);
frame.setSize(400, 400);
frame.setDefaultCloseOperation(frame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
我认为修改摆动不能在一个单独的线程来完成,所以我,有一个setText来改变在invokeLater
点击按钮JTextField的大小。这样做应该打破单线程规则,这会不会导致死锁?
从其他线程对Swing组件进行更改不会造成死锁您的程序(至少不是通常) - 只是JVM没有义务反映其他线程中某个线程所做状态的更改,除非有发生在之间的关系,例如块或访问volatile
字段。 JVM可能会决定只读取一次变量的值,并且不会在当前线程中重新读取它,这意味着您的更新永远不会被绘制UI的线程看到,或者可能会在稍后不可预知的时间内更新它。
使用invokeLater
插入更新到EDT确保有一个之前发生那setText
和接下来的绘制操作之间。
更新:正如你现在已经成功地通过移动使代码的僵局,你排队Runnable
,问题是,当你试图去排队就可以了操作的EDT尚未运行。
在上面的示例中,您正在使用单个线程。由于大多数GUI环境都使用事件队列来操作Swing。此队列包含必须处理的内容,如点击事件,文本框编辑事件。这些都是在所谓的GUI线程上执行的。 Swing不断重绘场景并处理队列中的事件。这些事件只能在一个线程中处理,这就是为什么当您在点击处理程序中进行长时间计算(或联网)时应用程序会冻结。当您拨打SwingUtilities.invokeLater
时,您的代码将被提交并放入事件队列中。当Swing有一段时间时,它会在GUI线程上执行它。
对于僵局需要具备以下条件:
- 至少有两个线程
- ,通过第一锁定他们
- 锁定发生在不同的顺序在不同的线程上的资源A和B的操作
潜在的死锁例子:
Thread1: Thread2:
lock(A) lock(B)
lock(B) lock(A) <---- may deadlock here
do stuff do stuff
free(B) free(A)
free(A) free(B)
您的示例和您在注释中链接的示例的主要区别在于,您在此处正在主线程上创建GUI(类似于其他示例),但在用户单击之前您不调用Swing的GUI线程在按钮上。 GUI构建在主线程上,不会干扰Swing线程。在另一个例子中,GUI由两个线程并行构建。
看到[这个](http://stackoverflow.com/questions/8865800/deadlock-when-using-settext-on-jtextarea-in-swing)的问题,他们有一个类似的设置使用invokeLater,但仍然设法陷入僵局。你说的为什么只有一个线程? – Aequitas
@Aequitas查看我的更新回答。 –
更正式地说,*必须*对死锁持有的条件是:互斥,等待,不先占和循环等待。 – ChiefTwoPencils
从不同线程调用Swing方法确实不明智,但不是因为死锁的风险。主要风险是:
- 螺纹干涉
- 内存一致性错误
根据The Event Dispatch Thread。死锁主要来自多线程中不正确的有序锁定机制。由于许多Swing对象显然没有适当的锁定,死锁并不是主要问题。
为什么在[这个](http://stackoverflow.com/questions/8865800/deadlock-when-using-settext-on-jtextarea-in-swing)问题他们得到一个类似的设置我的死锁?他们之间有什么区别 – Aequitas
@Aequitas对于初学者,你没有在Swing对象(框架)上同步,然后你在Swing事件线程开始之后提交你的任务(另一个尝试在任何之前提交它Swing已经启动)。 – chrylis
我看到了谢谢,我将invokeLater移入主体而不是按钮按下,现在它已经死锁。同步化的意思是什么? – Aequitas