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

Java 方法参数和局部变量是线程安全的

Java 方法参数和局部变量是线程安全的,java,multithreading,thread-safety,Java,Multithreading,Thread Safety,有人能证实下面的说法吗 方法中声明的方法参数和局部变量是线程 安全的;对于线程的每次调用,两者都是独占的 另一方面,全局变量是共享的 比如说 class MyThread implements Runnable{ int _tmp = 10; //SHARED BETWEEN t1, t2, t3, and so on public void run(){ testThreadConcurrency(arg); // arg is EXCLUSI

有人能证实下面的说法吗

方法中声明的方法参数和局部变量是线程 安全的;对于线程的每次调用,两者都是独占的

另一方面,全局变量是共享的

比如说

class MyThread implements Runnable{

    int _tmp = 10;      //SHARED BETWEEN t1, t2, t3, and so on

    public void run(){

        testThreadConcurrency(arg); // arg  is EXCLUSIVE FOR ALL invocation of testThreadConcurrency
    }

    public void testThreadConcurrency (int num){

        int tmp = 10;   //EXCLUSIVE FOR ALL invocation of testThreadConcurrency()

    }
}


public static void main(String[] args) {
        // TODO Auto-generated method stub

        MyThread _runn = new MyThread();

        Thread t1 = new Thread(_runn,"t1");
        Thread t2 = new Thread(_runn,"t2");
        Thread t3 = new Thread(_runn,"t3");
        t1.start();
        t2.start();             
        t3.start()
}
**

请检查以下程序的输出,以证明全局 变量是共享的

**


不完全是

MyThread _runn = new MyThread();  //you are using the same instance here ! delete this line
T1的
\u tmp
不与T2的
\u tmp
共享,因为它们是不同的
MyThread
实例(不是类变量,而是实例变量)

实际上,每次创建线程时都要重新实例化整个类:

new MyThread
如果属性实际上是类变量,则情况会有所不同:

static int _tmp = 10;
在这种情况下,您可能需要一些同步机制(
synchronized
block,或
volatile
关键字或任何其他适合情况的东西)

我想把它改为:

方法中声明的方法参数和局部变量是线程 安全的;对于线程的每次调用,两者都是独占的

但是,处理一个或多个全局变量的任何类的相同实例 在命中线程之间共享这些线程

最好的做法是避免线程之间共享实例的数量达到最大值,避免同步所有内容(只要性能/内存不受太大影响)

因此,您的代码片段遵循最佳实践:)

------------对您添加的代码段发表评论-----------------

MyThread _runn = new MyThread();  //you are using the same instance here ! delete this line
因此,实际上,在这种情况下,如果在声明每个线程时重用此实例,则该属性将是share:

Thread t1 = new Thread(_runn,"t1");
Thread t2 = new Thread(_runn,"t2");
Thread t3 = new Thread(_runn,"t3");
替换为:

Thread t1 = new Thread(new MyThread(), "t1"); //a new MyThread instance for each thread !
Thread t2 = new Thread(new MyThread(), "t2");
Thread t3 = new Thread(new MyThread(), "t3");
将输出(按预期:):

方法内声明的方法参数和局部变量是线程安全的;对于线程的每次调用,两者都是独占的

方法的每次调用。没有“线程调用”这样的东西,如果有,它也不够包容方法的调用涵盖了递归和多线程的情况

另一方面,全局变量是共享的


是的。

小心!参数和变量不是对象。假设多个线程各自输入一个方法来处理列表:

public Foo mumbler(List<Bar> barList) {
    ...
}

如果您有一个局部变量myStack,并且您调用了
pushValueOnStack(someValue,myStack),
它实际上会更改您的局部变量以指向堆栈的新顶部节点。这是参考电话。这在Java中从未发生过。

更新了一个解释,我同意您的看法,使用不同的可运行t1、t2和t3将tmp视为一个独立的资源。如果我让它成为“静态的”,那么它又会在所有人之间共享。我的问题是为什么“volatile”在那个地方不起作用……让它像“static”一样共享资源当然,
static
makeshared<代码>易失性与此示例无关。它只允许记忆障碍<代码>易失性与
静态
没有直接联系。两者都是不同的概念<代码>易失性强制主内存在另一个线程读取相关字段的值之前使用该字段的最新值进行更新。它充当“发生在”之前的事件<代码>易失性本身不共享某些内容。我看不出你的资格有任何意义。全局变量(即Java静态变量)是共享的,句号为。它与实例无关。您可能想添加另一段关于实例变量的内容,但您添加的关于全局(静态)变量的内容毫无意义。类测试{int var1;//全局变量/实例变量static int var2;//类变量}对不起!由于我想制作一个测试应用程序来演示“volatile”的用法,所有的混乱都会产生。但是,现在我知道,不可能用小程序来显示它,因为它与内存可见性有关。如果我使用相同的可运行对象创建N个线程,那么所有线程都将指向相同的全局成员。我们可以说,在这种情况下,全局变量的行为类似于类变量。谢谢James!来纠正我。我忘记了Java pass原语是作为CallByValue的,但是在引用的情况下使用CallByReference。因此,如果参数是reference类型,那么它们就不是线程安全的。再次感谢James!你澄清了我的想法。是的,Java只按值传递,引用与原语相比只有一个优势,即我们可以对其进行操作,但对于交换,两者的效果相同;这意味着我们无法在C/C++中借助CallByReference/CallByAddress实现同样的功能
public Foo mumbler(List<Bar> barList) {
    ...
}
pushValueOnStack(my_type_t value, struct node &top) {
    struct node new_node = malloc(sizeof(*new_node));
    new_node->value = value;
    new_node->next = top;
    top = new_node;
}