Java中同一对象的不同实例上的多线程

发布于 2024-09-06 12:52:44 字数 1088 浏览 4 评论 0原文

我了解到,每个类加载器都会将每个类字节代码加载到内存中一次,因此当一个线程正在执行某个方法的字节代码时,另一个线程出现了?

1 线程 -> 1 实例 - Foo == 没问题。

X 线程 -> 1 实例 - Foo == 需要处理,这一点很明确。

X 线程 -> X 个 实例 - Foo == ????

我应该确保没有任何混乱方法? 如果该方法使用实例级别变量,我可以确定它将使用正确的变量吗?

更新:

我发现我的问题对某些人来说不清楚,这是一个数字示例,

我有一个类类型Foo的对象,它没有同步!

我有 5 个 Foo 实例,每个实例都有 5 个线程运行,并访问实例 级别参数,例如:

class FOO {
     private SomeObject someObject=new SomeObject();

     private void problematicMethod(Data data) {
         someObject.doSomethingWithTheData(data);
         data.doSomethingWithSomeObject(someObject); 
// any way you want it use the data or export the data
     }
}

我问这里是否有问题,因为该类只有 1 字节代码和该对象的 5 实例访问该字节代码,所以如果我想防止它们在同一字节代码上重叠, 我应该怎么办?

谢谢, 亚当.

I've learned that every class byte code is been loaded to the memory once for each class loader, thus when a thread is executing the byte code of some method, and another thread comes along?

1 thread -> 1 instance - of class Foo == no problem.

X threads -> 1 instance - of class Foo == need to be handled this is clear.

X threads -> X respective instances - of class Foo == ????

should I make sure nothing is messed up in the method?
if the method uses a instance level variables, can I be sure it will use the right ones?

Update:

I see my question was not clear to some, here is an example with numbers

I have an object of class type Foo which has no synchronization!!

I have 5 instances of that Foo with 5 threads running for/in each of them, and accessing instance level parameters for example:

class FOO {
     private SomeObject someObject=new SomeObject();

     private void problematicMethod(Data data) {
         someObject.doSomethingWithTheData(data);
         data.doSomethingWithSomeObject(someObject); 
// any way you want it use the data or export the data
     }
}

I'm asking is there a problem here, since there is only 1 byte code of this class and 5 instances of this object that access this byte code, so if I want to prevent them from overlapping on the same byte code, what should I do?

Thanks,
Adam.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

_失温 2024-09-13 12:52:49

我了解到,每个类加载器都会将每个类字节代码加载到内存中一次,因此当一个线程正在执行某个方法的字节代码时,另一个线程就会出现?

类加载和字节代码在这里无关紧要。字节码是一组类似汇编的指令,JVM 将其解释并编译为本机机器代码。多个线程可以安全地遵循编码到字节码中的指令集。

1 个线程 -> 1 个实例 - Test 类,没问题

大部分是正确的。如果只有一个线程,则不需要立即确保任何线程安全。然而,忽略线程安全会限制增长和可重用性。

X 个线程 -> 1 个实例 - 类 Test,需要处理,这一点很清楚。

嗯,是的,出于线程可见性的原因并确保关键区域以原子方式执行,使用同步或锁定技术相当重要。当然,这一切都取决于对吗?如果您的类没有状态(实例或类变量),那么您实际上不需要使其线程安全(想想像 Java 的 Executors 、 Arrays 这样的实用程序类>,Collections 类)。

X 个线程 -> X 各自的实例 - Test 类,???

如果每个线程都有自己的 Test 类实例,并且多个线程之间没有共享任何单个实例,那么这与您的第一个示例相同。如果 Test 的实例被两个或多个线程引用,那么这与第二个示例相同。

如果该方法使用类级别变量,我可以确定它将使用正确的变量吗?

类变量是 Java 中的静态变量。已经发布了两个答案,它们强调使用同步来防止多个线程同时修改类变量的重要性。没有提到使用 synchronizedvolatile 来确保您不会看到类变量的过时版本的重要性。

I've learned that every class byte code is been loaded to the memory once for each class loader, thus when a thread is executing the byte code of some method, and another thread comes along?

Class loading and byte code is irrelevant here. Byte code is a set of assembly-like instructions which the JVM interprets and compiles into native machine code. More than one thread can safely follow the instruction sets encoded into the byte code.

1 thread -> 1 instance - of class Test, no problem

Mostly correct. If there is only a single Thread, then there is not any immediate need to make anything thread safe. However, ignoring thread safety would limit growth and re-usability.

X threads -> 1 instance - of class Test, need to be handled this is clear.

Well, yes, for thread visibility reasons and to ensure that critical regions are executed atomically, using synchronization or locking techniques is fairly important. Of course, it all depends right?! If your class doesn't have state (instance or class variables), then you don't really need to make it thread-safe (think utility class like Java's Executors, Arrays, Collections classes).

X threads -> X respective instances - of class Test, ????

If each thread has its own instance of class Test, and no single instance is shared amongst more than one thread, then this is the same as your first example. If an instance of Test is referenced by two or more threads, then this is the same as your second example.

if the method uses a class level variables, can I be sure it will use the right ones?

Class variables ARE static variables in Java. There are already two answers posted which emphasize the importance of using synchronized to prevent more than one thread from modifying a class variable at the same time. Not mentioned is the importance of using synchronized or volatile to make sure you don't see a stale version of the class variable.

ヅ她的身影、若隐若现 2024-09-13 12:52:49

您需要同步共享资源。如果该资源是类级字段,则应该在类本身上进行同步:

public class Foo {
  private static int someNumber = 0;
  // not thread safe
  public void inc_unsafe()  { 
    someNumber++;
  }

  // not thread safe either; we are sync'ing here on an INSTANCE of
  // the Foo class
  public synchronized void inc_also_unsafe()  { 
    someNumber++;
  }

  // here we are safe, because for static methods, synchronized will use the class
  // itself
  public static synchronized void inc_safe()  { 
    someNumber++;
  }

  // also safe, since we use the class itself
  public static synchronized void inc_also_safe()  { 
    synchronized (Foo.class) {
      someNumber++;
    }
  }
}

请注意,{{java.util.concurrent}} 提供了比 Java 的 {{synchronized}} 关键字更多的方法来保护共享数据。看看它,因为它可能是你想要的。

对于任何想要声称 int 递增已经是线程安全的人,请注意这只是一个示例,基本概念可以应用于任何事物。

You need to synchronize on the shared resource. If that resource is a class-level field, you should synchronize on the class itself:

public class Foo {
  private static int someNumber = 0;
  // not thread safe
  public void inc_unsafe()  { 
    someNumber++;
  }

  // not thread safe either; we are sync'ing here on an INSTANCE of
  // the Foo class
  public synchronized void inc_also_unsafe()  { 
    someNumber++;
  }

  // here we are safe, because for static methods, synchronized will use the class
  // itself
  public static synchronized void inc_safe()  { 
    someNumber++;
  }

  // also safe, since we use the class itself
  public static synchronized void inc_also_safe()  { 
    synchronized (Foo.class) {
      someNumber++;
    }
  }
}

Note that {{java.util.concurrent}} provides many more ways to protected shared data than Java's {{synchronized}} keyword. Look into it, as it might be what you want.

(For anyone that wants to claim that int incrementing is already thread-safe, please note this is just an example and the basic concept can be applied to anything.)

金橙橙 2024-09-13 12:52:49

添加到戴夫的答案 ,如果您有多个作用于不同静态成员的静态方法,最好在单独的静态对象上进行同步。

public class Foo {
  private static int someNumber = 0;
  private static int otherNumber = 0;
  private static final Object lock1 = new Object();
  private static final Object lock2 = new Object();

  public static void incSomeNumber() {
    synchronized (lock1) {
      someNumber++;
    }
  }

  public static void incOtherNumber() {
    synchronized (lock2) {
      otherNumber++;
    }
  }
}

这样,两个不同的线程就可以同时调用 incSomeNumberincOtherNumber,而不会陷入同步困境。


编辑

这是与AtomicInterger相同的示例。请注意,不需要显式锁定。 AtomicInterger 上的所有操作都是原子的,并使用硬件操作实现。因此它们会带来更好的性能。

import java.util.concurrent.atomic.AtomicInteger;

public class Foo {
  private static AtomicInteger someNumber = new AtomicInteger(0);
  private static AtomicInteger otherNumber = new AtomicInteger(0);

  public static int incSomeNumber() {
    return someNumber.incrementAndGet();
  }

  public static int incOtherNumber() {
    return otherNumber.incrementAndGet();
  }
}

Adding to dave's answer, if you have multiple static methods that work on different static members, it is better to synchronize on separate static objects.

public class Foo {
  private static int someNumber = 0;
  private static int otherNumber = 0;
  private static final Object lock1 = new Object();
  private static final Object lock2 = new Object();

  public static void incSomeNumber() {
    synchronized (lock1) {
      someNumber++;
    }
  }

  public static void incOtherNumber() {
    synchronized (lock2) {
      otherNumber++;
    }
  }
}

In this way, two different threads can call incSomeNumber and incOtherNumber at the same time without getting stuck on synchronization.


EDIT

Here is the same example with AtomicInterger. Note that no explicit locking is required. All operations on AtomicIntergers are atomic and implemented using hardware operations. So they result in better performance.

import java.util.concurrent.atomic.AtomicInteger;

public class Foo {
  private static AtomicInteger someNumber = new AtomicInteger(0);
  private static AtomicInteger otherNumber = new AtomicInteger(0);

  public static int incSomeNumber() {
    return someNumber.incrementAndGet();
  }

  public static int incOtherNumber() {
    return otherNumber.incrementAndGet();
  }
}
诗化ㄋ丶相逢 2024-09-13 12:52:49

所有线程都应该进入同一个类加载器。 10 个线程使用 FOo.class,所有 10 个线程都将具有相同的对象。在不同的类加载器中获得相同类的唯一方法是:

a)您编写了自己的代码来实现类加载器的魔法
b) 你做了一些奇怪的事情,比如将你的代码包含在一个 war 中,以及一个共享的 tomcat lib 文件夹中......并且执行了正确的事件顺序,导致从不同的位置加载 2 个副本。

在所有正常情况下......您创建一个类,该类对象恰好有 1 个副本,并且(此)上的所有同步都将跨您的整个应用程序。

All threads should go to the same class loader. 10 threads using FOo.class, all 10 will have the same exact object. The only way you would get the same class in different classloaders would be if

a) You wrote your own code that did class loader magic
b) You did something weird like include your code both inside a war, and inside of a shared tomcat lib folder... and did the right sequence of events to cause 2 copies to be loaded from different places.

In all normal cases.. you make a class, there is exactly 1 copy of the class object, and all synchronization on (this) will be across your entire application.

电影里的梦 2024-09-13 12:52:49

我认为,实例变量作为局部变量对于每个线程都是唯一的。所以默认情况下它是线程安全的。但是,是的,它仍然需要通过同步来照顾。

And I think, instance variable as local variable is unique to each thread. So by default it is thread safe.But yes, it is still needed to be taken care by synchronization.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文