synchronized关键字修饰非静态方法与静态方法的区别

Posted chongaizhen

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了synchronized关键字修饰非静态方法与静态方法的区别相关的知识,希望对你有一定的参考价值。

这里我们先创建ObjLock类,并实现Runnable接口。并创建一个Demo类,具有被synchronized关键字修饰的非静态方法与静态方法。

非静态方法

public class ObjLock implements Runnable 

    Demo demo;

    public ObjLock(Demo demo)
        this.demo = demo;
    

    public void run() 
        demo.getI(Thread.currentThread().getName());
    

    public static void main(String[] args)
        Demo demo = new Demo(1);
        Thread thread = new Thread(new ObjLock(demo),"thread0");
        Thread thread1 = new Thread(new ObjLock(demo),"thread1");
        Thread thread2 = new Thread(new ObjLock(new Demo(2)),"thread2");
        thread.start();
        thread1.start();
        thread2.start();
    



class Demo

    static int i;

    Demo(int i)
        this.i=i;
    

    public static synchronized void staticGetI(String s)
        for (int j=0;j<10000;j++)
            System.out.println(i+"---------"+s);
        
    

    public synchronized void getI(String s)
        for (int j=0;j<10000;j++)
            System.out.println(i+"---------"+s);
        
    

运行程序,可以看到如下结果:

1---------thread0
1---------thread0
2---------thread2
1---------thread0
2---------thread2
1---------thread0
1---------thread1
1---------thread1
2---------thread2
1---------thread1
1---------thread1
1---------thread1

可以看到Thread0和Thread2交替出现,Thread1和Thread2交替出现,但Thread0和Thread1不会交替出现。

因为对非静态方法加锁,实际上是对调用该方法的对象加锁。Thread0和Thread1用的是同一个对象,所以互斥,但是Thread2则不受影响。

静态方法

将getI方法改成static之后

public void run() 
    demo.staticGetI(Thread.currentThread().getName());

测试发现三个线程均互斥。

当synchronized修饰一个static方法时,多线程下,获取的是类锁(即Class本身,注意:不是实例),作用范围是整个静态方法,作用的对象是这个类的所有对象。

一个对象在两个线程中分别调用一个静态同步方法和一个非静态同步方法

修改代码

public void run() 
    if (Thread.currentThread().getName().equals("thread0"))
        demo.staticGetI(Thread.currentThread().getName());
    else if (Thread.currentThread().getName().equals("thread1"))
        demo.getI(Thread.currentThread().getName());
    
 

结果:不会产生互斥。

解释:因为虽然是一个对象调用,但是两个方法的锁类型不同,调用的静态方法实际上是类对象在调用,即这两个方法产生的并不是同一个对象锁,因此不会互斥,会并发执行。

以上是关于synchronized关键字修饰非静态方法与静态方法的区别的主要内容,如果未能解决你的问题,请参考以下文章

synchronized修饰普通方法,修饰静态方法,修饰代码块,修饰线程run方法 比较

synchronized修饰普通方法和静态方法

Java synchronized 关键字详解

Java中synchronized用在静态方法和非静态方法上面的区别

Synchronized原理

synchronized关键字的使用及互斥锁的实现