真正的静态同步方法如何在Java中工作?

时间:2016-05-05 13:14:06

标签: java multithreading

我试图探索static synchronized method我得到的理论概念是它获得了对课程的锁定,而不是实例。但是我没能创建一个可以测试它的例子。

这里我创建了要测试的代码,但两个实例同时访问static synchronized method

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();
    }
}

static synchronized我得到此输出。

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

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

2 个答案:

答案 0 :(得分:2)

您可以在方法sleep中添加a()作为下一个:

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个线程同时执行这个块,就像在下一个输出中一样,实际上你连续两次没有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

static synchronized方法和synchronized方法有什么区别?

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

<强>静态

例如,这样做:

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

等同于:

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

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

非静态

例如,这样做:

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

等同于:

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

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

答案 1 :(得分:0)

您需要让a()方法运行很长时间,以确保方法调用不重叠。这是一种方法:

package com.example;

public class Demo {

    public static synchronized void a() {
        for (int i = 0; i < 5; i++) {
            System.out.println("A Method " +  Thread.currentThread().getName());
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) {
        final Demo obj = new Demo();
        final Demo obj2 = new Demo();

        Thread one = new Thread() {
            @Override
            public void run() {
                obj.a(); // same as Demo.run() 
            }
        };
        Thread two = new Thread() {
            @Override
            public void run() {
                obj2.a(); // same as Demo.run() 
            }
        };

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