8 java concurrency multithreading static-methods thread-safety
我正在尝试确定是否需要担心我编写的几个关键类中的线程安全性.我已经阅读了几篇文章/现有的SO问题,我一直看到线程安全的反复定义:
线程安全意味着对象或类的字段始终保持有效状态,如其他对象和类所观察到的,即使由多个线程同时使用也是如此.
好.我有点儿了.但是我在这里缺少一个很大的难题:
当多个线程使用同一个类实例时,或者只是在使用任何2个以上的实例时,线程安全是否仅起作用?
假设我有一个Dog不包含静态方法或字段的类,并且假设我有5 Dog个不同线程中正在操作的5个不同实例.我是否需要关注线程安全?我会说"不",因为没有静态字段/方法,并且每个线程都有自己的实例,Dog其状态独立于其他4个实例而存在.(1)这是对的吗?如果没有,为什么?
现在让我们说我添加一个静态方法Dog:
public void woof() {
this.isWoofing = true;
}
public static void makeWoof(Dog dog) {
dog.woof();
}
Run Code Online (Sandbox Code Playgroud)
我现在需要关注线程安全吗?每个线程都有自己的a实例Dog,但现在它们共享相同的静态makeWoof()方法,这会改变Dog它正在运行的状态.我仍然说"不".(2)这是对的吗?如果没有,为什么?
鉴于这两个例子,在我看来,当多个线程在一个类的同一个实例上运行时,线程安全只是一个问题.但是你给每个线程自己的实例的那一刻,似乎我可以做任何我想要的那个实例,而不用担心其他线程内部发生了什么.(3)这是对的吗?如果没有,为什么?它们有什么例外吗?提前致谢!
您对线程安全的假设是正确的.它归结instance为由多个线程修改的字段/状态.
在你的第一个问题中,线程都操纵它们自己的实例,Dog因此该方法是线程安全的.
在第二个问题中,实例被传递给静态方法,因此您再次使用该类的不同实例.如果Dog类包含静态字段,静态方法操作那些不是线程安全的字段,但非最终静态字段实际上从不是线程安全的.
它并不是真正的共享实例.这是关于共享的状态
考虑到这一点:
1:正确 - 如果您的线程不在共享状态下运行,它们本质上是线程安全的.
2:不正确(sorta): - 在此特定静态方法的特定示例中,未触及共享状态,但静态方法可以创建/操作共享状态.
3:见1和2
举个例子,让我们在OP的Dog类中引入一小部分共享状态:
static Integer numberOfBarksToday=0;
Run Code Online (Sandbox Code Playgroud)
因为它是静态的,所以它是共享的.所以现在,静态方法(OP makeWoof方法的修改版本)可以操作:
public static void makeWoof(Dog dog) {
dog.woof();
synchronized(Dog.numberOfBarksToday) {
Dog.numberOfBarksToday++;
}
}
Run Code Online (Sandbox Code Playgroud)
我刚刚意识到,当我创建上面的示例时,我将访问与习惯同步.通过该同步,此特定访问是线程安全的(当然,对numberOfBarksToday的所有其他访问也必须同步).
如果没有同步,多个线程调用此方法,您将倾向于低估今天的树皮数量:T0)numberOfBarksToday = 0; T1)线程A检查树皮数量(第一部分++),得到0. T2)线程B检查树皮数量,得到0. T3)线程A设置树皮数量为1 T4)线程B设置树皮数量为1
而且没有考虑是否在共享对象中,赋值方法是原子的.
同步会阻止上述所有情况,并引入内存屏障,以便所有线程看到numberOfBarksToday的相同值.
| 归档时间: |
|
| 查看次数: |
3006 次 |
| 最近记录: |