【问题标题】:Synchronization on arguments of static methods静态方法的参数同步
【发布时间】:2014-03-25 20:30:51
【问题描述】:

我有一个关于 java 与静态方法同步的问题。

更准确地说,我有一个具有静态方法的类,可以由多个线程同时使用。我的类的主要静态方法有一个参数,并依次调用其他辅助静态方法并传递此参数。

我的问题如下:由于该类可以同时被多个线程使用,是否存在另一个线程将参数替换为另一个线程的风险?

我曾想过在我的主函数的参数变量上使用一个同步块,包括方法的整个代码(以及对辅助函数的调用),但我不确定这是一个好的解决方案。

谁能帮帮我?

【问题讨论】:

  • 一个单独的线程如何跳转到另一个线程的栈帧并替换一个参数值?
  • 不,参数不能被线程调用修改,因为Java是传值的。
  • 参数的类型是什么?集合还是数组?
  • 即使参数是对调用静态方法的类(this)的引用?
  • 它对班级有什么影响?该方法是否以任何方式改变状态?也就是说,它们会更新类中的静态值吗?

标签: java multithreading static synchronization block


【解决方案1】:

我的问题如下:由于该类可以同时被多个线程使用,是否存在另一个线程将参数替换为另一个线程的风险?

不,没有。您混淆了static 和堆栈存储。

 static int x;

 static void someMethod(int y1, SomeObject y2) {
     int z;
     ...
 }

在线程情况下,所有线程都访问同一字段x。您需要担心该字段的同步。然而,即使someMethod(...) 是一个static 方法,y1 参数和z 方法字段对于调用线程来说是本地的。其他线程无法访问该内存,因为它位于线程的调用堆栈中。

这个例外是参数y2,因为它是一个对象。 Java 是按值传递的,而基元是在堆栈上传递的。但是,当您按值传递对象时,您会传递其引用,因此两个线程可以传递相同的对象引用,您需要担心那里的同步。

顺便说一句,虽然肯定允许在线程之间调用静态方法,但这并不是最好的模式。如果可能的话,实例是要走的路。它们可以共享静态常量字段等,但从其他 static 方法调用各种 static 方法听起来过于混乱。

【讨论】:

    【解决方案2】:

    我认为参数的值不可能被另一个线程“替换”......线程有自己的方法上下文......所谓的调用堆栈。例如,您可以有 50 个线程在同一时间调用 String.valueOf() 以获得不同的值,并且每个线程都将获得它们自己的线程上下文中的值。

    【讨论】:

    • 您需要了解参数类型。如果参数是非线程保存集合,那么它的值可能会发生意外变化。
    • @deanosaur 静态方法并不意味着只有一个执行上下文。
    • OP 询问一个线程传递给另一个线程的独立方法的参数是否可以被另一个线程仅使用自己的参数调用该方法来更改,答案是否定的.如果我们谈论的是在集合上处理数据的工作线程,您需要同步线程以便在主线程上处理该集合,那么您所说的将是真正的 deanosaur,如果线程同步错误,您的集合可以被修改由另一个线程,而您的主线程认为可以继续。
    • @rpg711 实际上我认为他正在从所有线程传递相同的参数(类本身)。如果类有一个静态成员boolean busy,第一个线程将其设置为true,而静态方法做了while(busy),会发生什么?
    • 这取决于其他线程是否可以访问它。我认为您的示例是错误的代码,静态成员甚至不存在于“this”实例引用中,它们存在于类本身并且是类型限定的,而不是实例限定的。传递它与传递对您能想到的任何其他可变对象的引用完全相同,在这种情况下,相同的规则适用于当您从另一个线程修改该对象中包含的值时发生的情况。在这种情况下,您需要对该对象的状态进行锁定,这不是这里的问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多