我多年没有做任何线程,需要一点重置:
如果我有一个类的多个实例,两个线程是否需要同步,即使它们与不同的实例通信?
实施例
假设我有一个方法课。该方法递增计数器并返回当前计数。
有两个主题。每个线程都有自己的计数器类实例,并重复调用该方法。没有锁定或同步。线程会互相踩到吗?
答案 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”传递给方法,它们将访问完全不同的内存位置,因此不需要线程同步。