java - Java 中静态同步方法到底是如何工作的?

标签 java multithreading

我正在尝试探索静态同步方法我得到的理论概念是它在类上获取锁,而不是在实例上。但我未能创建一个可以测试它的示例。

这里我创建了要测试的代码,但是两个实例都同时访问静态同步方法

class Demo{
    public static synchronized void a(){
        System.out.println("A Method " +  Thread.currentThread().getName());
    }
}
public class StaticSyn{
    public static void main(String[] args){
        Demo obj = new Demo();
        Demo obj2 = new Demo();

        Thread one = new Thread(){
            @Override
            public void run(){
                int i=0;
                while(i<5){
                    obj.a();
                try{
                    Thread.sleep(100);
                }catch(InterruptedException e){

                }
                    i++;
                }
            }
        };
        Thread two = new Thread(new Runnable(){
            @Override
            public void run(){
                int i=0;
                while(i<5){
                    obj2.a();
                    try{
                        Thread.sleep(100);
                    }catch(InterruptedException e){     }
                    i++;
                }
            }
        });

        one.start();
        two.start();
    }
}

使用静态同步我得到这个输出。

A Method Thread-0
A Method Thread-1
A Method Thread-1
A Method Thread-0
A Method Thread-1
A Method Thread-0
A Method Thread-0
A Method Thread-1
A Method Thread-1
A Method Thread-0

如果没有 static 关键字,我将得到此输出。

A Method Thread-0
A Method Thread-1
A Method Thread-1
A Method Thread-0
A Method Thread-0
A Method Thread-1
A Method Thread-0
A Method Thread-1
A Method Thread-1
A Method Thread-0

那么,问题出在哪里呢?以及如何测试只有一个对象正在访问静态同步方法。

最佳答案

您可以在方法 a() 中添加 sleep,如下所示:

public static synchronized void a(){
    System.out.println("Before sleep: A Method " +  Thread.currentThread().getName());
    try{
        Thread.sleep(100);
    } catch(InterruptedException e){
        Thread.currentThread().interrupt();
    }
    System.out.println("After sleep: A Method " +  Thread.currentThread().getName());
}

然后您将看到不会像下一个输出那样有 2 个线程同时执行此 block ,实际上您永远不会连续两次 Before sleep:

Before sleep: A Method Thread-0
After sleep: A Method Thread-0
Before sleep: A Method Thread-1
After sleep: A Method Thread-1
Before sleep: A Method Thread-0
After sleep: A Method Thread-0
Before sleep: A Method Thread-1
After sleep: A Method Thread-1
Before sleep: A Method Thread-0
After sleep: A Method Thread-0
Before sleep: A Method Thread-1
After sleep: A Method Thread-1
Before sleep: A Method Thread-0
After sleep: A Method Thread-0
Before sleep: A Method Thread-1
After sleep: A Method Thread-1
Before sleep: A Method Thread-0
After sleep: A Method Thread-0
Before sleep: A Method Thread-1
After sleep: A Method Thread-1

静态同步方法和同步方法有什么区别?

主要区别在于用于同步访问的对象。

静态

例如这样做:

class Demo {
    public static synchronized void a() {
        // Rest of the method
    }
}

相当于:

class Demo {
    public static void a() {
        synchronized (Demo.class) {
            // Rest of the method
        }
    }
}

换句话说,在静态方法的情况下,它使用代表类本身的对象来同步访问。

非静态

例如这样做:

class Demo {
    public synchronized void a() {
        // Rest of the method
    }
}

相当于:

class Demo {
    public void a() {
        synchronized (this) {
            // Rest of the method
        }
    }
}

换句话说,在非静态方法的情况下,它使用类的当前实例来同步访问。

关于java - Java 中静态同步方法到底是如何工作的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37051595/

相关文章:

java - 如何使用另一个线程从方法中获取结果

c# - 线程监控 Queue<Actions>

java - 如何从接口(interface)数组列表中获取某个对象

multithreading - Vulkan中的多线程渲染(生成命令缓冲区)比单线程慢

java - 在 Java 8 中使用 IntStream.filter 时如何跳过特定的数组索引

java - 从 C++ 到 Java 的转变

与打包和mayavi相关的Python死锁?

python - 线程可以切换CPU吗?

java - 在 JTree 中,只有处理树才会扩展,但不会扩展树选择 - Java Swing

java - 如何在 XLS 报表中隐藏交叉表列标题 - 摘要区域中的交叉表和子报表