java 中的线程安全和实例
Thread-Safety and Instances in java
我已经阅读了很多关于线程安全的文章,并且对一个对象的多个实例是否会影响线程安全感到困惑。下面举例说明:
假设我们有一个名为 RGBColor 的 class,用户可以设置红色、绿色和蓝色的值,然后 return 颜色。
Public Class RGBColor {
private int red;
private int green;
private int blue;
Public RGBColor(int red, int green, int blue){
this.red = red;
this.green = green;
this.blue = blue;
}
Public void setColor(int red, int green, int blue){
this.red = red;
this.green = green;
this.blue = blue;
}
Public RGBColor getColor(){
return this;
}
}
现在,如果程序创建了多个 class 实例,例如:
RGBColor red = new RGBcolor(255,0,0);
RGBColor blue = new RGBcolor(0,0,255);
现在问题来了。 class 的这些实例是否完全独立?我的意思是线程安全会成为一个问题吗?毕竟据我了解,它们应该是完全不同的对象,在 RAM 中具有不同的分配。
另一个问题是变量和方法是否是静态的,例如
Public Class RGBColor {
private static int RED;
private static int GREEN;
private static int BLUE;
Public static void setColor(int red, int green, int blue){
RED = red;
GREEN = green;
BLUE = blue;
}
}
在线程安全方面如何处理静态变量和方法?
ps:我已经更新了第二个例子,因为它有缺陷。
Are these instances of the class are totally independent? I mean would
thread safety would be an issue?
实例之间是独立的,是的。
线程安全问题是因为多个线程可能以并发方式访问一个实例,并且其中一个或两个线程对实例状态进行了一些修改。
例如,假设您创建了一个 RGBColor
的实例,并且多个线程可以操作该实例。
现在,我们要求您
setColor()
调用不应与自身的其他调用交错。
在那里,你有一个竞争条件,你应该处理这个。
要处理它,您可以使用 synchronized
语句包围 setColor()
语句,并使字段 volatile
确保始终更新每个线程的内存:
private volatile int red;
private volatile int green;
private volatile int blue;
...
public void setColor(int red, int green, int blue){
synchronized (this){
this.red = red;
this.green = green;
this.blue = blue;
}
}
How are the static variables and methods would be handled when it
comes to thread safety?
对于静态变量,与实例变量相同。
对于实例方法,可以在实例上的锁上实现线程安全。
对于静态方法,应该在 class 本身的锁上实现。
你不应该担心 "thread safety" 这里。因为你得到的是更基本的东西错误。拥有一个 class 的多个实例是没有意义的 - 当相应的字段都是静态的时。
换句话说:在你的第二个例子中,拥有一个 red
和一个 blue
RGBColor 对象是没有意义的——因为你实例化的所有对象都会相互覆盖!最后一个获胜...
除此之外,在您的第一个示例中:方法 setColor()
可能会导致线程安全问题。因为该方法可能导致您最终处于不一致状态(当两个线程在 "same" 时间调用 相同 对象上的 setter - 但是不同的说法)。
换句话说:
- 首先花点时间学习一下 static 是什么,以及为什么你的第二个代码输入如此糟糕 "bad"
- 然后理解:一旦 "shared" 数据可被多个线程访问,线程安全就很重要。因为那时你必须确保对 "shared" 数据的 read/write 操作总是定义明确的。
第一种情况,对象有实例变量,对象是相互独立存在的。修改一个不会影响其他。
在第二种情况下,静态字段属于class,不属于任何一个对象。构造函数用于创建实例?不是为了填充静态变量,在这种情况下有一个构造函数是令人困惑和不必要的。同样在 getColor 中使用它也不起作用,静态方法中没有 RGBColor 的实例。
对于第一种情况,如果您取消设置器并将实例变量设为最终变量,那么您的对象将是不可变的,从而使它们可以安全地用于多线程。
对于第二种情况,多个线程可以覆盖彼此的工作,并且没有任何东西可以让其他线程看到更改。 (仅仅因为一个线程改变了一个值并不意味着它立即对其他线程可见。)
如果你真的想要这个 class 范围内的一组值,你可以创建一个不可变对象并将其分配给静态 volatile 变量,这样更新将是原子的并且对其他线程可见。
回答你的第一个问题。 YES 不同的对象在 JVM 中会有不同的哈希码。但是,当您考虑同时访问同一对象的事务时,您将不得不对对象使用线程安全(如果有对象修改),您可以使用
synchronized
methods.to 中的修饰符确保线程安全。当且仅当不同系统同时访问同一个对象。
回答你的第二个问题。 java 中的静态或非静态对象只有在该对象的修饰符 同步 时才是线程安全的。除此之外,您可以使用线程池和倒计时闩锁来有效地处理具有多个线程的对象
我已经阅读了很多关于线程安全的文章,并且对一个对象的多个实例是否会影响线程安全感到困惑。下面举例说明:
假设我们有一个名为 RGBColor 的 class,用户可以设置红色、绿色和蓝色的值,然后 return 颜色。
Public Class RGBColor {
private int red;
private int green;
private int blue;
Public RGBColor(int red, int green, int blue){
this.red = red;
this.green = green;
this.blue = blue;
}
Public void setColor(int red, int green, int blue){
this.red = red;
this.green = green;
this.blue = blue;
}
Public RGBColor getColor(){
return this;
}
}
现在,如果程序创建了多个 class 实例,例如:
RGBColor red = new RGBcolor(255,0,0);
RGBColor blue = new RGBcolor(0,0,255);
现在问题来了。 class 的这些实例是否完全独立?我的意思是线程安全会成为一个问题吗?毕竟据我了解,它们应该是完全不同的对象,在 RAM 中具有不同的分配。
另一个问题是变量和方法是否是静态的,例如
Public Class RGBColor {
private static int RED;
private static int GREEN;
private static int BLUE;
Public static void setColor(int red, int green, int blue){
RED = red;
GREEN = green;
BLUE = blue;
}
}
在线程安全方面如何处理静态变量和方法?
ps:我已经更新了第二个例子,因为它有缺陷。
Are these instances of the class are totally independent? I mean would thread safety would be an issue?
实例之间是独立的,是的。
线程安全问题是因为多个线程可能以并发方式访问一个实例,并且其中一个或两个线程对实例状态进行了一些修改。
例如,假设您创建了一个 RGBColor
的实例,并且多个线程可以操作该实例。
现在,我们要求您
setColor()
调用不应与自身的其他调用交错。
在那里,你有一个竞争条件,你应该处理这个。
要处理它,您可以使用 synchronized
语句包围 setColor()
语句,并使字段 volatile
确保始终更新每个线程的内存:
private volatile int red;
private volatile int green;
private volatile int blue;
...
public void setColor(int red, int green, int blue){
synchronized (this){
this.red = red;
this.green = green;
this.blue = blue;
}
}
How are the static variables and methods would be handled when it comes to thread safety?
对于静态变量,与实例变量相同。
对于实例方法,可以在实例上的锁上实现线程安全。
对于静态方法,应该在 class 本身的锁上实现。
你不应该担心 "thread safety" 这里。因为你得到的是更基本的东西错误。拥有一个 class 的多个实例是没有意义的 - 当相应的字段都是静态的时。
换句话说:在你的第二个例子中,拥有一个 red
和一个 blue
RGBColor 对象是没有意义的——因为你实例化的所有对象都会相互覆盖!最后一个获胜...
除此之外,在您的第一个示例中:方法 setColor()
可能会导致线程安全问题。因为该方法可能导致您最终处于不一致状态(当两个线程在 "same" 时间调用 相同 对象上的 setter - 但是不同的说法)。
换句话说:
- 首先花点时间学习一下 static 是什么,以及为什么你的第二个代码输入如此糟糕 "bad"
- 然后理解:一旦 "shared" 数据可被多个线程访问,线程安全就很重要。因为那时你必须确保对 "shared" 数据的 read/write 操作总是定义明确的。
第一种情况,对象有实例变量,对象是相互独立存在的。修改一个不会影响其他。
在第二种情况下,静态字段属于class,不属于任何一个对象。构造函数用于创建实例?不是为了填充静态变量,在这种情况下有一个构造函数是令人困惑和不必要的。同样在 getColor 中使用它也不起作用,静态方法中没有 RGBColor 的实例。
对于第一种情况,如果您取消设置器并将实例变量设为最终变量,那么您的对象将是不可变的,从而使它们可以安全地用于多线程。
对于第二种情况,多个线程可以覆盖彼此的工作,并且没有任何东西可以让其他线程看到更改。 (仅仅因为一个线程改变了一个值并不意味着它立即对其他线程可见。)
如果你真的想要这个 class 范围内的一组值,你可以创建一个不可变对象并将其分配给静态 volatile 变量,这样更新将是原子的并且对其他线程可见。
回答你的第一个问题。 YES 不同的对象在 JVM 中会有不同的哈希码。但是,当您考虑同时访问同一对象的事务时,您将不得不对对象使用线程安全(如果有对象修改),您可以使用
synchronized
methods.to 中的修饰符确保线程安全。当且仅当不同系统同时访问同一个对象。
回答你的第二个问题。 java 中的静态或非静态对象只有在该对象的修饰符 同步 时才是线程安全的。除此之外,您可以使用线程池和倒计时闩锁来有效地处理具有多个线程的对象