繁体   English   中英

在不同的线程中使用对象是否安全,但不能同时使用?

[英]Is it safe to use an object in different threads, but NOT at the same time?

我到处都读过,如果一个字段由不同的线程同时使用,则需要某种同步,如果只有一个线程使用它,则不需要它。 但是,如果它被不同的线程使用,但不能同时使用呢? 我们来看一下这样的代码:

Thing thing = new Thing();
Thread t1 = new Thread(new MyRunnable(thing));
Thread t2 = new Thread(new MyRunnable(thing));
t1.start();
t1.join();//Wait for t1 to finish
t2.start();

MyRunnable是:

class MyRunnable implements Runnable {
    //skipped constructor and field "private final Thing thing"
    public void run() {
        thing.someUpdate();
    }
}

安全吗? 是否t1可以看到t1所做的所有更新?

在这种情况下,更改是可见的,因为Thread.joinThread.start在两个线程中的操作之间创建了先发生关系。 请参阅内存一致性错误

  • 当一个语句调用Thread.start时,与该语句之前发生过关系的每个语句也与新线程执行的每个语句都有一个before-before关系。 新线程可以看到导致创建新线程的代码的影响。

  • 当一个线程终止并导致另一个线程中的Thread.join返回时,终止线程执行的所有语句都与成功连接后的所有语句有一个before-before关系。 现在,执行连接的线程可以看到线程中代码的效果。

如果您未按此顺序使用这些方法,则可能无法看到更改。 线程不需要同时运行以引起问题,因为值可以缓存在线程中,或者可能发生某些优化等。

我认为这个问题太抽象了。 问题的一般答案“是否t1可以看到t1所做的所有更新?” 是是的”。 但它们只会因为你运行线程的方式而可见。 示例中的线程不是并行的。 所以,是的,在这个例子中,两个线程都可以看到MyRunnable的字段。 但是MyRunnable类本身并不是线程安全的。 如果它将与并发线程一起使用,您可能会遇到麻烦。 这取决于MyRunnable.someUpdate()的细节。 您应该为您的字段使用“volatile”关键字,“java.util.concurrent。*”类或任何同步机制(如果有必要)。 也许这个文档将有助于启动: https//docs.oracle.com/javase/tutorial/essential/concurrency/atomic.html

在您的情况下,它是安全的,因为两个线程不在同一时间运行。

join()方法是一个阻塞方法,等待一个线程完成。 t2应该看到t1的所有更新。

在这种情况下它是安全的。 事物对象上的t1所做的更改将对t2可见。 如果没有t1.join(); 代码不是线程安全的。

t1.start();
t1.join();//Wait for t1 to finish
t2.start();

暂无
暂无

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

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