Java 多个同步关键字如何在一个类中工作?

Java 多个同步关键字如何在一个类中工作?,java,thread-safety,synchronize,Java,Thread Safety,Synchronize,假设一个线程在一个同步块中执行。另一个线程能否获得其他同步块上的锁 如果在同步块内对非同步方法进行方法调用,会发生什么情况?该方法是线程安全的吗? 如果我们尝试从同步实例方法访问静态变量会怎么样??每次,访问每个实例中的同步块的每个线程都会尝试修改静态变量。不是吗?在这种情况下,我们如何保证线程安全 另一个线程能否获得其他同步块上的锁 不可以,一次只能运行一个同步方法。对另一个同步方法的调用必须等到第一个方法完成。以下章节对此进行了描述: …同一对象上的两个同步方法调用不可能交错。当一个线程为一

假设一个线程在一个同步块中执行。另一个线程能否获得其他同步块上的锁
如果在同步块内对非同步方法进行方法调用,会发生什么情况?该方法是线程安全的吗?


如果我们尝试从同步实例方法访问静态变量会怎么样??每次,访问每个实例中的同步块的每个线程都会尝试修改静态变量。不是吗?在这种情况下,我们如何保证线程安全

另一个线程能否获得其他同步块上的锁

不可以,一次只能运行一个同步方法。对另一个同步方法的调用必须等到第一个方法完成。以下章节对此进行了描述:

…同一对象上的两个同步方法调用不可能交错。当一个线程为一个对象执行同步方法时,调用同一对象块的同步方法的所有其他线程(暂停执行),直到第一个线程对该对象执行完毕

如果在同步块内对非同步方法进行方法调用,会发生什么情况?该方法是线程安全的吗

如果只从属于此对象的同步方法调用非同步方法,则可以认为它是线程安全的,因为一次只有一个线程可以执行一个调用(同步)方法

请注意,正如@Ordous在下面指出的,静态同步方法锁定在类上,而非静态同步方法锁定在实例上。因此,非静态方法可以与属于所讨论类的静态方法交错

  • 不,任何其他线程将无法执行另一个块,该块在您的案例中获得同一对象的锁
    args

  • 否。从同步代码块调用的另一个方法将不是线程安全的。如果它没有synchronized关键字,任何其他线程都可以从任何其他代码块调用它,因为该线程不需要获取任何锁来执行该方法

  • 这是一种常见的误解,即
    synchronized
    关键字锁定了一段代码

    同步的
    关键字做什么?

    它锁定对象而不是方法。因此,如果您将
    synchronized
    关键字放在方法前面,那么它将锁定
    对象。因此,任何其他线程都不能执行具有
    synchronized
    关键字的任何其他方法

    这与
    静态
    非静态
    方法不同,因为当同步静态方法时,它不会锁定
    ,但会锁定默认类对象,即
    A.class
    对象。如果您有另一个静态同步方法,那么任何其他线程都不会执行该方法

    sync blocks
    的情况下,它将获得对象上的锁,该对象在您的情况下作为参数传递,它是
    args

    因此,如果在其他任何地方有另一个
    同步块
    在同一对象上获取锁,那么它将不得不等待,直到第一个线程完成并释放锁。

    同步代码上始终存在锁。要访问代码线程,必须获取密钥、解锁、运行并返回密钥

    存在一个对象级锁,该锁是整个对象的锁,而不是某个方法或块的锁。因此,即使单个实例上有多个同步块或方法,也只有一个线程可以获取密钥并访问同步代码。然后它将把密钥交还给对象,然后其他线程可以继续获取密钥并访问同步代码

    如果您想知道声明为syncrhonized的静态方法会发生什么情况(因为它们没有与之关联的对象/实例),那么在这种情况下,类本身也始终存在一个锁。要访问类的任何
    同步静态
    部分,线程必须从类获取密钥以解锁锁


    注意:-我提到的锁和键只是为了帮助理解,没有方法或方法来访问键或任何由JVM内部维护的东西。

    首先,一个类中可以有多个同步方法。这是通过以下方式实现的:

    • 将方法声明为已同步

    • 同步方法

    根据您的问题,如果线程属于同一类(多个线程请求相同的资源,那么同一类的两个对象不能同时访问特定的资源)。持有互斥锁的线程(互斥锁)在监视器中。所有其他此类线程都必须等待监视器

    Java线程调度程序确保当前在监视器中的线程可能需要任何同步方法,即持有锁的线程。因此,不允许其他线程同时执行这些方法。
    非同步方法不是这样的,它们可以并发执行。

    不,该方法将根据需要执行,不一定分别执行。但是一个对象有一个锁。那么,为什么另一个线程会获得锁,因为它已经被第一个线程占用了呢?哦,糟糕,很好。那里有一个小的大脑屁。编辑。除了一个s同一对象的static和非static方法。它们可以交错(熟悉Java的人会知道它们是实例和类方法,因此具有不同的锁,但如果给出OPs问题,这将是一个有用的注释)在这种情况下,它的“args”更清楚地说,如果我们尝试从同步实例方法访问静态变量,每次每个线程访问e中的同步块,会怎么样
    package anonymous;
    
    public class A {
    public static int counter=0;
    
    public static void main(String[] args) {
    
        synchronized (args) {
            //some logic
        }
    
        synchronized (args) {
            //some logic
    
        }
     }        
    
    }