Java中同一对象的不同实例上的多线程
我了解到,每个类加载器都会将每个类字节代码加载到内存中一次,因此当一个线程正在执行某个方法的字节代码时,另一个线程出现了?
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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
类加载和字节代码在这里无关紧要。字节码是一组类似汇编的指令,JVM 将其解释并编译为本机机器代码。多个线程可以安全地遵循编码到字节码中的指令集。
大部分是正确的。如果只有一个线程,则不需要立即确保任何线程安全。然而,忽略线程安全会限制增长和可重用性。
嗯,是的,出于线程可见性的原因并确保关键区域以原子方式执行,使用同步或锁定技术相当重要。当然,这一切都取决于对吗?如果您的类没有状态(实例或类变量),那么您实际上不需要使其线程安全(想想像 Java 的 Executors 、 Arrays 这样的实用程序类>,
Collections
类)。如果每个线程都有自己的 Test 类实例,并且多个线程之间没有共享任何单个实例,那么这与您的第一个示例相同。如果 Test 的实例被两个或多个线程引用,那么这与第二个示例相同。
类变量是 Java 中的静态变量。已经发布了两个答案,它们强调使用同步来防止多个线程同时修改类变量的重要性。没有提到使用
synchronized
或volatile
来确保您不会看到类变量的过时版本的重要性。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.
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.
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).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.
Class variables ARE
static
variables in Java. There are already two answers posted which emphasize the importance of usingsynchronized
to prevent more than one thread from modifying a class variable at the same time. Not mentioned is the importance of usingsynchronized
orvolatile
to make sure you don't see a stale version of the class variable.您需要同步共享资源。如果该资源是类级字段,则应该在类本身上进行同步:
请注意,{{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:
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.)
添加到戴夫的答案 ,如果您有多个作用于不同静态成员的静态方法,最好在单独的静态对象上进行同步。
这样,两个不同的线程就可以同时调用
incSomeNumber
和incOtherNumber
,而不会陷入同步困境。编辑
这是与
AtomicInterger
相同的示例。请注意,不需要显式锁定。AtomicInterger
上的所有操作都是原子的,并使用硬件操作实现。因此它们会带来更好的性能。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.
In this way, two different threads can call
incSomeNumber
andincOtherNumber
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 onAtomicInterger
s are atomic and implemented using hardware operations. So they result in better performance.所有线程都应该进入同一个类加载器。 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.
我认为,实例变量作为局部变量对于每个线程都是唯一的。所以默认情况下它是线程安全的。但是,是的,它仍然需要通过同步来照顾。
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.