Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 在不同线程中使用对象安全吗,但不能同时使用?_Java_Multithreading_Concurrency - Fatal编程技术网

Java 在不同线程中使用对象安全吗,但不能同时使用?

Java 在不同线程中使用对象安全吗,但不能同时使用?,java,multithreading,concurrency,Java,Multithreading,Concurrency,我到处都读到,如果一个字段同时被不同的线程使用,则需要某种形式的同步,如果它只被一个线程使用,则不需要。但是如果它被不同的线程使用,但不是同时使用呢? 让我们来看看这样的代码: 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 f

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

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所做的所有更新是否都可以被t2看到?

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

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

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

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

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

在这种情况下,更改是可见的,因为
Thread.join
Thread.start
在两个线程中的操作之间的关系发生之前创建。见:

  • 当语句调用Thread.start时,每个具有 与该语句的关系之前发生的事件也具有 在与新语句执行的每个语句的关系之前发生 线导致新代码创建的代码的效果 线程对新线程可见

  • 当一个线程终止并导致另一个线程中的thread.join终止时 return,则终止线程执行的所有语句 a发生在与以下所有语句的关系之前 成功加入。线程中代码的效果现在是可见的 到执行联接的线程


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

someUpdate()写入Thing对象的字段,这些字段只是私有字段(不是易失性的,没有同步)。然后有几种方法:1。将这些字段标记为易变字段(正如上面文档中所写的那样,它将风险降至最低,但问题仍然存在)2。使“void synchronized someUpdate()”无效。您将是100%安全的,但您的代码将是缓慢的,因为这意味着此时只有一个线程将执行此方法。3.同步someUpdate()中的特殊部件,这些部件是关键部分。事实上,如果任务如此抽象,很难说该做什么。这真的取决于你想用你的代码实现什么。我会选择一个好方法(可能使一些更新同步,因为我不希望它被多个线程同时调用)谢谢!顺便说一句,如果您总是这样使用它:“t1.start();t1.join();t2.start();”您的变量将可见。但MyRunnable类的代码将是非线程安全的。因此,也许你是对的,在某些更新中添加“synchronized”将使你的代码更加健壮。你可能应该引用你链接到的文档的相关部分,以防万一。