简体   繁体   English

Java:ActionListener.actionPerformed内部的并发

[英]Java: Concurrency inside ActionListener.actionPerformed

today I started deal with concurrency in Java (probably that was bad idea...) 今天我开始处理Java中的并发(可能这是个坏主意......)

I read some articles about it. 我读了一些关于它的文章。 At the beginning I understood it but now I am confused... 一开始我明白了,但现在我很困惑......

I'm going straight to the point. 我直截了当地说。 Suppose we have this class 假设我们有这门课

public class Test implements ActionListener
{
    private boolean bool;

    public void process()
    {
        if (bool)
            // ...

        return bool;
    }

    @Override
    public void actionPerformed(ActionEvent e)
    {
        // We can suppose that this method belongs to JButton or so...
        // And if I am not wrong then this method is fired in EDT, so it means it runs in
        // other thread (Event Dispatch Thread) in contrast with this class... So there are
        // two threads...

        bool = ... ? true : false;
    }

    // ...
}

My confusion: 我的困惑:

In actionPerformed() we modify the value of property bool and in the same time we can access the property inside process() (again if I am not wrong)... For me it seems that there can occur to some error or so... My solution is that property bool should be volatile or method process() should be tagged as synchronized and statement actionPerformed()中我们修改属性bool的值,同时我们可以访问process()内部的属性(如果我没有错的话)......对我来说似乎可能会出现一些错误。 ..我的解决方案是属性bool应该是volatile或方法process()应该被标记为synchronized和statement

bool = ... ? true : false;

should be as: 应该是:

synchronized (this)
{
    bool = ... ? true : false;
}

This is little primitive example, but we can consider bool property as Object, String, etc... and in actionPerformed() we will set it to null and in process() will be thrown a NullPointerException for example... 这是一个很小的原始示例,但我们可以将bool属性视为Object,String等...而在actionPerformed()中我们将其设置为null,并且在process()中将抛出NullPointerException,例如...

What you think? 你认为呢? I want to know why anyone use synchronizing inside listeners... I have not found anyone... 我想知道为什么有人在侦听器中使用同步...我没有找到任何人......

Thanks 谢谢

Regards brolinko 关心brolinko

EDIT #1: process() is never called within EDT... When I create an instance of Test for example in main() method then the instance runs inside a thread as main() and in main() I can call the process() ... So there are two threads in this case if I am not wrong... 编辑#1:在EDT中从不调用process() ...当我在main()方法中创建一个Test实例时,实例在一个线程内作为main()运行,而在main()中我可以调用该进程()...所以如果我没有错的话,在这种情况下有两个线程......

The Java memory model and the Java multithreading rules apply to all classes and threads. Java内存模型和Java多线程规则适用于所有类和线程。 The fact that your class implements ActionListener is irrelevant. 您的类实现ActionListener的事实是无关紧要的。

If two threads access a shared variable and you expect writes by one thread to be visible by reads from the other threads, then some kind of synchronization must be used to access the shared variable (synchronized access, make the variable volatile, or use a thread-safe object like an AtomicBoolean). 如果两个线程访问共享变量并且您希望一个线程的写入通过其他线程的读取可见,则必须使用某种同步来访问共享变量(同步访问,使变量易变,或使用线程) -safe对象,如AtomicBoolean)。

You're not wrong, if a variable is used by two or more threads, writes should be made visible by using the appropriate memory barriers (synchronized/volatile/java.util.concurrent). 你没错,如果一个变量被两个或多个线程使用,应该通过使用适当的内存屏障(synchronized / volatile / java.util.concurrent)使写入可见。

In this case though, the question is: is process() not also called from the EDT? 在这种情况下,问题是:是否还没有从EDT调用process() If it is, there are no multiple threads to talk about and hence the code works, albeit dangerously unsafe. 如果是,则没有多个线程要讨论,因此代码可以工作,尽管危险地不安全。

Update: You're saying process() isn't called from the EDT. 更新:您说没有从EDT调用 process() Your code will still happen to work because although you don't put a memory barrier on your write, the implementation of the EDT does . 您的代码仍然可以正常工作,因为虽然您没有在写入时设置内存障碍 ,但EDT的实现确实如此 In theory, relying on this is a dangerous idea because there's no guarantee this will stay this way. 理论上,依靠这是一个危险的想法,因为不能保证这将保持这种方式。 In practice, there are so many brittle AWT applications out there that it's unlikely to change. 在实践中,有那么多脆弱的AWT应用程序,它不太可能改变。 (As pointed out by @jtahlborn, this barrier still only applies to calls from within the EDT) (正如@jtahlborn指出的那样,这个障碍仍然只适用于EDT内部的电话)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM