两个线程引用了非同步类的非共享实例。线程问题?

时间:2014-12-01 17:35:02

标签: java multithreading synchronization thread-safety

我多年没有做任何线程,需要一点重置:

如果我有一个类的多个实例,两个线程是否需要同步,即使它们与不同的实例通信?

实施例

假设我有一个方法课。该方法递增计数器并返回当前计数。

有两个主题。每个线程都有自己的计数器类实例,并重复调用该方法。没有锁定或同步。线程会互相踩到吗?

5 个答案:

答案 0 :(得分:5)

  

有两个主题。每个线程都有自己的计数器类实例,并重复调用该方法。没有锁定或同步。线程会互相踩到吗?

只要没有从另一个线程中读取写入一个线程的数据,他们就不会赢。

特定的多线程策略称为线程限制:您不能跨线程共享任何内容。这是使程序线程安全的最简单方法之一。

答案 1 :(得分:1)

除非两个线程都更新计数器的同一个实例,否则不需要任何锁定或同步。如果他们都有一个反例,并且他们只读/写他们自己的反例,那就不会有问题。

答案 2 :(得分:0)

如果没有任何static字段(在类实例之间固有共享)和并发外部数据访问(文件,流,DDE,数据库等),则不应遇到任何线程问题。

由于static个字段和所有并发外部数据对象都是“唯一的”,因此您必须同步访问它们。这正是为什么建议使用immutables&不要在多线程运行中使用static数据,除非因某些与同步相关的原因(例如锁等)而使数据具有可变/静态。

请注意,计数器本质上是可变的(它改变了它的状态) - 但在大多数现实情况下,你可以安全地使用不可变对象(字符串,不可变集合等)

进一步阅读:https://docs.oracle.com/javase/tutorial/essential/concurrency/immutable.html

答案 3 :(得分:0)

如果只有一个线程正在访问对象中的给定对象/字段,则它将是线程安全的。

示例:

public class ThreadSafe {
  int counter;
  public void increment() {...}
}

public class NotThreadSafe {
  static int counter;
  public static void increment() {...}
}

答案 4 :(得分:0)

嗯,这有点复杂,但看到你在堆栈交换上的评级,我认为你可以消化它:

我们都知道对象包含数据和方法。 当我们创建一个对象时,对象的“数据部分/实例变量/字段(它们对于类中的全局数据都是同名的)”存储在我们称为堆空间的内存中的数据结构中。该数据结构可以由“this pointer”引用。 所以这意味着如果我们有两个不同的对象,它们会有不同的指针。 方法没有任何独立分配。 什么时候我们执行像这样的方法 obj1.feature() 它意味着在obj1上应用“特征”。在此过程中,运行时系统会将obj1的“this pointer”传递给“feature”。 方法中的内部变量在被称为帧的数据结构上被分配空间,该帧被推入堆栈。任何未在方法内声明的变量都假定在全局数据结构中,并且指向它的指针会自动附加,因此globalvaraiabe变为this.globalvariable
所以我们可以清楚地看到,如果我们将不同的“this pointer”传递给方法,它们将访问完全不同的内存位置,因此不需要线程同步。