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_Synchronize - Fatal编程技术网

Java多线程混乱

Java多线程混乱,java,multithreading,synchronize,Java,Multithreading,Synchronize,代码示例1: class Test { MyObj myObj = new MyObj(); public void test() { // doing my other stuff synchronized (myObj) { // accessing myObj } } } class Test { MyObj myObj = new MyObj(); public void

代码示例1:

class Test {
    MyObj myObj = new MyObj();

    public void test() {
        // doing my other stuff
        synchronized (myObj) {
            // accessing myObj
        }
    }
}
class Test {
    MyObj myObj = new MyObj();

    public void test() {
        synchronized (myObj) {
            // doing my other stuff

            // accessing myObj
        }
    }
}
class Test {
    MyObj myObj = new MyObj();

    public synchronized void test() {
        // doing my other stuff

        // accessing myObj
    }
}
代码示例2:

class Test {
    MyObj myObj = new MyObj();

    public void test() {
        // doing my other stuff
        synchronized (myObj) {
            // accessing myObj
        }
    }
}
class Test {
    MyObj myObj = new MyObj();

    public void test() {
        synchronized (myObj) {
            // doing my other stuff

            // accessing myObj
        }
    }
}
class Test {
    MyObj myObj = new MyObj();

    public synchronized void test() {
        // doing my other stuff

        // accessing myObj
    }
}
代码示例3:

class Test {
    MyObj myObj = new MyObj();

    public void test() {
        // doing my other stuff
        synchronized (myObj) {
            // accessing myObj
        }
    }
}
class Test {
    MyObj myObj = new MyObj();

    public void test() {
        synchronized (myObj) {
            // doing my other stuff

            // accessing myObj
        }
    }
}
class Test {
    MyObj myObj = new MyObj();

    public synchronized void test() {
        // doing my other stuff

        // accessing myObj
    }
}

我想在上面的代码快照中保持对myObj的线程安全。那么,上面哪种代码快照更可取?为什么

代码示例1是合适的。
因为先锁定对象,然后再执行其他操作是不合适的。

代码示例1是合适的。
因为先锁定对象,然后再执行其他操作是不合适的。

根据我在开源项目中看到的代码,第一个代码示例更好,因为当您不再需要对象时,可以释放它,以便其他线程可以访问它。

根据我在开源项目中看到的代码,第一个代码示例更好,因为当您不再需要对象时,可以释放它,以便其他线程可以访问它。

您的示例中没有一个包含足够的信息

数据在哪里?不变量是什么?线程何时/何地/如何访问数据

“线程安全”没有数据就没有意义。有状态类的文档通常会保证其方法如何提升实例的状态。“线程安全”意味着即使在多个线程调用这些方法时,也能满足这些保证。但是如果类不是有状态的,或者没有这样的保证,那么“线程安全”就没有任何意义


注意:代码示例1与其他示例相比有一个重要的优势:互斥(即synchronized块)更小。根据经验,您希望互斥体尽可能小。如果“my other stuff”不关心受互斥体保护的数据,那么它就不应该发生在互斥体中,因为这会阻止其他线程访问数据,并且不会因为任何有用的原因而阻止它们



p.p.S.:@Ordous注释+1:除非您能看到可以修改或检查状态的每个代码块,否则无法知道某个对象的状态是否是线程安全的。由于在您的示例中,
myObj
不是
private
,因此我们必须假设其他地方有代码可以修改或检查其状态。由于我们看不到该代码,我们必须假设
myObj
不是线程安全的。

您的示例中没有一个包含足够的信息

数据在哪里?不变量是什么?线程何时/何地/如何访问数据

“线程安全”没有数据就没有意义。有状态类的文档通常会保证其方法如何提升实例的状态。“线程安全”意味着即使在多个线程调用这些方法时,也能满足这些保证。但是如果类不是有状态的,或者没有这样的保证,那么“线程安全”就没有任何意义


注意:代码示例1与其他示例相比有一个重要的优势:互斥(即synchronized块)更小。根据经验,您希望互斥体尽可能小。如果“my other stuff”不关心受互斥体保护的数据,那么它就不应该发生在互斥体中,因为这会阻止其他线程访问数据,并且不会因为任何有用的原因而阻止它们



p.p.S.:@Ordous注释+1:除非您能看到可以修改或检查状态的每个代码块,否则无法知道某个对象的状态是否是线程安全的。由于在您的示例中,
myObj
不是
private
,因此我们必须假设其他地方有代码可以修改或检查其状态。因为我们看不到那个代码,所以我们必须假设
myObj
不是线程安全的。

在整个方法上保持一个锁(如果它很长)是非常昂贵的。它不仅可以阻止整个威胁,还可以阻止不需要同步的代码。其次,有时您可能不使用您的
myObj
,在这种情况下,示例2和3将是不好的

简而言之:仅同步块的一部分,即您正在处理对象的位置。您还可以在对象上使用
volatile
,检查其值,而无需同步块。请记住,锁定可能代价高昂

但是,当您的方法足够短,或者只包含带有myObj的代码时,将整个方法同步是一个很好的解决方案

public void test() {
   // doing my other stuff, not concernign myObj
    synchronized (myObj) {
        // do things with myObj (read/write)
    }
   // doing my other stuff, not concernign myObj
}

看看这个例子。

在整个方法上保持一个锁(如果它很长的话)是非常昂贵的。它不仅可以阻止整个威胁,还可以阻止不需要同步的代码。其次,有时您可能不使用您的
myObj
,在这种情况下,示例2和3将是不好的

简而言之:仅同步块的一部分,即您正在处理对象的位置。您还可以在对象上使用
volatile
,检查其值,而无需同步块。请记住,锁定可能代价高昂

但是,当您的方法足够短,或者只包含带有myObj的代码时,将整个方法同步是一个很好的解决方案

public void test() {
   // doing my other stuff, not concernign myObj
    synchronized (myObj) {
        // do things with myObj (read/write)
    }
   // doing my other stuff, not concernign myObj
}

看看这个例子。

首选代码示例1。代码示例1-->监视器是在myObj上获得的,因此它是线程安全的代码示例2-->监视器是在myObj上获得的,因此它是线程安全的,内部或外部的其他内容是不相关的代码示例3-->锁/监视器是在调用test()方法的对象上获得的,无论是myObj还是任何其他对象,取决于调用,这些都不是首选项,因为您将
myObj
package protected而不是private=PCode示例1作为首选项。代码示例1-->监视器是在myObj上获得的,因此它是线程安全的代码示例2-->监视器是在myObj上获得的,因此它是线程安全的,内部或外部的其他内容是不相关的代码示例3-->锁/监视器是在调用test()方法的对象上获得的,无论是myObj还是任何其他对象,