Java 当线程尝试调用静态和非静态同步方法时会发生什么?

Java 当线程尝试调用静态和非静态同步方法时会发生什么?,java,multithreading,Java,Multithreading,我有一门课 public class ThreadExample extends Thread{ static int count = 0; public static synchronized int increment(){ return count++; } public synchronized int decrement(){ return count--; } } 这里我有一个静态方法和一个非静态方法 第

我有一门课

public class ThreadExample extends Thread{

    static int count = 0;
    public static synchronized  int increment(){
        return count++;
    }
    public synchronized int decrement(){
        return count--;
    }

}
这里我有一个静态方法和一个非静态方法

第一个线程1调用了同步的方法increment(),它在类级别获得锁。
这里我的问题是,如果另一个thread2正在调用decrement()方法,thread2是否会获取decrement()上的锁以及它是如何工作的?

调用同步静态方法会尝试获取类对象的锁。(
ThreadExample
),在调用同步的非静态方法时,尝试获取特定实例对象的锁。因此,本质上您获得了两个不同的锁,因此您的代码不是线程安全的。数据
计数
可能由于竞争条件而损坏

调用同步静态方法试图获取类对象的锁。(
ThreadExample
),在调用同步的非静态方法时,尝试获取特定实例对象的锁。因此,本质上您获得了两个不同的锁,因此您的代码不是线程安全的。数据
计数
可能由于竞争条件而损坏

关键字
synchronized
有两种可能的用途。它可以用作方法的修饰符,也可以用作语句。此外,
synchronized
修饰符可以与
static
组合,在这种情况下,目标对象将是封闭类而不是封闭实例

如果方法是“静态同步的”
,则会在所包含的
类的
对象上获取锁,在
ThreadExample.class上就是这样。
虽然它们被编译成不同的字节码,但以下两种方法是等效的:

public class Foo {
    // static method with synchronized modifer
    public static synchronized void foo1() {
        // ...
    }
    // equivalent synchronized statement
    public static void foo2() {
        synchronized (Foo.class) {
            // ...
        }
    }
}
public class Foo {
    // instance method with synchronized modifier
    public synchronized void foo3() {
        // ...
    }
    // equivalent synchronized statement
    public void foo4() {
        synchronized (this) {
            // ...
        }
    }
}
如果一个方法是
同步的
(没有static),则会在实例本身上获取锁。虽然它们被编译成不同的字节码,但以下两种方法是等效的:

public class Foo {
    // static method with synchronized modifer
    public static synchronized void foo1() {
        // ...
    }
    // equivalent synchronized statement
    public static void foo2() {
        synchronized (Foo.class) {
            // ...
        }
    }
}
public class Foo {
    // instance method with synchronized modifier
    public synchronized void foo3() {
        // ...
    }
    // equivalent synchronized statement
    public void foo4() {
        synchronized (this) {
            // ...
        }
    }
}
因此,
increment()
decreation()
是不同的
同步的
,可能存在竞争条件

因此,变量
count
没有得到足够的保护,无法防止并发更新

++
-->
本身不能是原子的,因为递增或递减一个值需要一个读更新写周期。从技术上讲,它可以是原子的,因为一些CPU通过提供相应的指令来提供原子性,这些指令将保留为自己获得的总线/地址,直到执行操作为止。但是JVM并不依赖这些东西

如果需要原子int,您可能需要查看
java.util.concurrent.atomic.AtomicInteger

如何在C中进行
同步
synchronized
通过虚拟机环境方法
MonitorEnter()
MonitorExit()
实现

陷阱 当您使用
synchronized
修改器时,您同步的对象或多或少是
公共的
,即其他对象和类也可见。
java.lang.Object
的监视功能是
public
,它为
synchronized
提供了底层功能,以及本机函数
MonitorEnter()
/
MonitorExit()
和等待池方法
wait()
notify()
notifyAll()
。如果“其他人”也在使用“您的对象/您的类”进行同步,这可能会导致意外的错误和死锁

因此,实际上不使用
synchronized
修饰符,而是在
private
锁定对象上使用
synchronized
语句已成为一种模式,如下所示:

public class Foo {
    private final Object lock = new Object();
    public void foo() {
        synchronized (lock) {
            // ...
        }
    }
}
现在,
Foo
不能再被其他正在同步的人干扰或阻止。您可能会认为这可能有一个合理的用例,但我认为如果您有一个跨对象/类边界锁定的用例,那么设计中可能有一个很大的缺陷——东西不够自包含

如果需要类锁而不是实例锁,只需将变量设为静态

请注意,在执行序列化时,必须注意lock对象。最简单的方法是实际上不使用对象,但是:

public class Lock implements Serializable {}

如果要保存序列化存储,可以声明锁
transient
,并在反序列化过程中重新创建锁,但要小心
transient final
,它们需要反射或
readResolve()
,但情况不同。
synchronized
关键字有两种可能的用途。它可以用作方法的修饰符,也可以用作语句。此外,
synchronized
修饰符可以与
static
组合,在这种情况下,目标对象将是封闭类而不是封闭实例

如果方法是“静态同步的”
,则会在所包含的
类的
对象上获取锁,在
ThreadExample.class上就是这样。
虽然它们被编译成不同的字节码,但以下两种方法是等效的:

public class Foo {
    // static method with synchronized modifer
    public static synchronized void foo1() {
        // ...
    }
    // equivalent synchronized statement
    public static void foo2() {
        synchronized (Foo.class) {
            // ...
        }
    }
}
public class Foo {
    // instance method with synchronized modifier
    public synchronized void foo3() {
        // ...
    }
    // equivalent synchronized statement
    public void foo4() {
        synchronized (this) {
            // ...
        }
    }
}
如果一个方法是
同步的
(没有static),则会在实例本身上获取锁。虽然它们被编译成不同的字节码,但以下两种方法是等效的:

public class Foo {
    // static method with synchronized modifer
    public static synchronized void foo1() {
        // ...
    }
    // equivalent synchronized statement
    public static void foo2() {
        synchronized (Foo.class) {
            // ...
        }
    }
}
public class Foo {
    // instance method with synchronized modifier
    public synchronized void foo3() {
        // ...
    }
    // equivalent synchronized statement
    public void foo4() {
        synchronized (this) {
            // ...
        }
    }
}
因此,
increment()
decreation()
是不同的
同步的
,可能存在竞争条件

因此,变量
count
没有得到足够的保护,无法防止并发更新

++
-->
本身不能是原子的,因为递增或递减一个值需要一个读更新写周期。从技术上讲,它可以是原子的,因为一些CPU通过prov为它提供原子性