在java中的synchronized方法或块中使用静态成员
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在java中的synchronized方法或块中使用静态成员相关的知识,希望对你有一定的参考价值。
当我在实例方法上使用synchronized方法时,监视器与'this'相关联。另一方面,当我在我的类(静态)方法上进行同步时,监视器与类对象相关联。当我在非静态方法中使用静态变量时会发生什么?会同步吗?
例如,
public class A{
public static int reg_no = 100;
public synchronized void registration(){
A.reg_no = some operation...
}
}
在上面的例子中,两个或多个线程的静态变量qazxsw poi会发生什么竞争方法qazxsw poi?
使用reg_no
注释成员函数时,该方法将在对象的实例上同步。如果要在静态变量上进行同步,则必须手动同步类对象:
registration()
请注意,上面获得了两个锁,如果任何其他代码在另一个顺序中获得相同的两个锁,则可以导致synchronized
。您可能希望从方法中删除public synchronized void registration() {
synchronized (A.class) {
A.reg_no = some operation ...
}
}
,只留下deadlocks。
对变量(静态或实例)的访问不同步。该方法的同步将防止单个实例的竞争条件,无论变量(静态或实例)如何
如果你想要防范多个实例,你必须在类文字上进行同步,但这看起来确实是错误的。
(经过进一步思考后修改)
对于上面给出的示例,您可以通过声明您的静态int像punkers建议的那样挥发。
但是在一般情况下 - 例如,如果你的静态变量是一个具有可变状态的对象......
synchronized实例方法意味着只允许持有对象实例锁的线程在该类A实例的该方法中进行,并且当该线程在该方法中完成并释放锁时,任何其他线程使用任何其他线程进入任何同步块相同的锁将“看到”您所做的更改。
它不会阻止另一个线程对静态变量进行更改:
- 直接从外部类A为静态变量赋值(变量是公共的!)
- 调用类A的静态方法(同步或其他),它重新分配静态变量,因为它将使用不同的锁
- 调用A类的非同步实例方法
使用synchronized方法通常有点危险 - 它们可能导致死锁,因为锁可以由其他使用您的类/实例作为同步块的目标的代码从外部获取:
synchronized
要么
synchronized (A.class)
更好的方法可能是将静态变量设为私有,添加私有本地变量以用作锁(因此无法在外部锁定),并在方法中的synchronized块中使用私有本地锁:
synchronized (objectOfTypeA) { ... } // takes the instance lock
不,您需要将方法与类同步,例如。 synchronized (A.getClass()) { ... } // takes the class lock
。
如果你的问题是与其他线程共享该变量,我会将静态变量声明为volatile,而不是在synchronized方法中添加另一个synchronized块。
以上是关于在java中的synchronized方法或块中使用静态成员的主要内容,如果未能解决你的问题,请参考以下文章
[Java] synchronized在代码块中修饰.class与this的区别