java - 为什么这段代码不会死锁?

标签 java swing deadlock

我正在调查 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);
}

我认为对 swing 的修改不能在单独的线程中完成,所以我有一个 setText 来更改 invokeLater 中单击按钮时的 JTextField。这样做应该打破单线程规则,这不会导致死锁吗?

最佳答案

从其他线程更改 Swing 组件不会死锁您的程序(至少通常不会)——只是 JVM 没有义务反射(reflect)在一个线程中所做的状态更改在其他线程中,除非存在 happens-before 关系,例如 synchronized block 或访问 volatile 字段。 JVM 可能决定只读取一次变量的值并且永远不会在当前线程中重新读取它,这意味着您的更新永远不会被绘制 UI 的线程看到,或者它可能会在以后某个不可预测的时间更新它.

使用 invokeLater 将更新插入 EDT 可确保 happens-beforesetText 和下一个绘制操作之间。

更新:由于您现在已经通过移动 Runnable 队列的位置成功地使代码死锁,问题是 EDT 尚未运行时您尝试将其上的操作排队。

关于java - 为什么这段代码不会死锁?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34914800/

相关文章:

java - JRadioButton 正在选择最后一个

java - 如何动态创建和删除 JTextArea

java - 死锁困惑

java - 拒绝执行异常。泳池尺寸太小?

java - Web 客户端的 ObjectMapper

JFrame 不同类中的 Java JTable

sql - 查询中的锁定顺序(postgresql)

.NET 应用程序因 GC 线程死锁而挂起

java - 在 Android 中创建自己的样式

java - 在数组中查找对编号