Java中Synchronized关键字的爱恨情仇

目录

一、简介

二、synchronized修饰普通方法(对象锁)

三、synchronized修饰静态方法(类锁)

四、synchronized修饰代码块(也分类锁、对象锁)

五、总结


一、简介

        Synchronized直译为同步的意思,常在代码中用于解决多线程的并发问题。它是一种同步锁,可以确保线程互斥的访问同步代码。

        Java中每一个对象都可以作为锁,这是synchronized实现同步的基础。

        普通同步方法(实例方法),锁是当前实例对象 ,进入同步代码前要获得当前实例的锁。

        静态同步方法,锁是当前类的class对象 ,进入同步代码前要获得当前类对象的锁,同步方法块,锁是括号里面的对象,对给定对象加锁,进入同步代码库前要获得给定对象的锁。

二、synchronized修饰普通方法(对象锁)

测试代码:

class B{
    
    synchronized public void mB(String value) {
        for (int i = 0; i < 10; i++) {
            System.out.println(value);
            try{
                Thread.sleep(150);
            }catch(Exception e){
                
            }
        }
    }

    synchronized public void mC(String value) {
        for (int i = 0; i < 10; i++) {
            System.out.println(value);
            try{
                Thread.sleep(150);
            }catch(Exception e){
                
            }
        }
    }
    
}

public class Main {
    
    public static void main(String[] agrs){
        System.out.println("Main 线程 开始运行!");
        final B b1 = new B();
        Thread t1 = new Thread(){
            @Override
            public void run(){
                System.out.println("t1 开始运行!");
                b1.mB("HAHA");
                System.out.println("t1 结束运行!");
            }
        };
        t1.start();
        Thread t2 = new Thread(){
            @Override
            public void run(){
                System.out.println("t2 开始运行!");
                b1.mC("XIXI");
                System.out.println("t2 结束运行!");
            }
        };
        t2.start();
           
        System.out.println("Main 线程 结束运行!");
    }
}

打印结果:

Main 线程 开始运行!
Main 线程 结束运行!
t1 开始运行!
HAHA
t2 开始运行!
HAHA
HAHA
HAHA
HAHA
HAHA
HAHA
HAHA
HAHA
HAHA
t1 结束运行!
XIXI
XIXI
XIXI
XIXI
XIXI
XIXI
XIXI
XIXI
XIXI
XIXI
t2 结束运行!

结论:修饰普通方法的时候,锁的是当前对象。
如果创建个新对象b2,则不能保持同步!!
例如下面的代码,无法保持同步!!!

public class Main {
    
    public static void main(String[] agrs){
        System.out.println("Main 线程 开始运行!");
        final B b1 = new B();
        Thread t1 = new Thread(){
            @Override
            public void run(){
                System.out.println("t1 开始运行!");
                b1.mB("HAHA");
                System.out.println("t1 结束运行!");
            }
        };
        t1.start();
        
        final B b2 = new B();
        Thread t2 = new Thread(){
            @Override
            public void run(){
                System.out.println("t2 开始运行!");
                b2.mC("XIXI");
                System.out.println("t2 结束运行!");
            }
        };
        t2.start();
        System.out.println("Main 线程 结束运行!");
    }
}

三、synchronized修饰静态方法(类锁)

B 类修改为如下:

class B{
    
    synchronized static public void mB(String value) {
        for (int i = 0; i < 10; i++) {
            System.out.println(value);
            try{
                Thread.sleep(150);
            }catch(Exception e){
                
            }
        }
    }

    synchronized static public void mC(String value) {
        for (int i = 0; i < 10; i++) {
            System.out.println(value);
            try{
                Thread.sleep(150);
            }catch(Exception e){
                
            }
        }
    }
    
}

结论:就算两个不同的对象,也可以保持同步!!!

四、synchronized修饰代码块(也分类锁、对象锁)

class B{
 public void mB(String value) {
        synchronized(B.class){
            for (int i = 0; i < 10; i++) {
                System.out.println(value);
                try{
                    Thread.sleep(150);
                }catch(Exception e){
                    
                }
            }
        }
        
    }
 public void mC(String value) {
        synchronized(B.class){
            for (int i = 0; i < 10; i++) {
                System.out.println(value);
                try{
                    Thread.sleep(150);
                }catch(Exception e){
                    
                }
            }
        }
    }
}

上面是类锁:所有对象可以保持同步。

class B{
 public void mB(String value) {
        synchronized(this){
            for (int i = 0; i < 10; i++) {
                System.out.println(value);
                try{
                    Thread.sleep(150);
                }catch(Exception e){
                    
                }
            }
        }
        
    }
 public void mC(String value) {
        synchronized(this){
            for (int i = 0; i < 10; i++) {
                System.out.println(value);
                try{
                    Thread.sleep(150);
                }catch(Exception e){
                    
                }
            }
        }
    }
}

上面是对象锁:同一对象可以保持同步,不同对象不可保持同步。

五、总结

1、 无论synchronized关键字加在方法上还是对象上,如果它作用的对象是非静态的,则它取得的锁是对象;如果synchronized作用的对象是一个静态方法或一个类,则它取得的锁是对类,该类所有的对象同一把锁。 
2、每个对象只有一个锁(lock)与之相关联,谁拿到这个锁谁就可以运行它所控制的那段代码。 
3、实现同步是要很大的系统开销作为代价的,甚至可能造成死锁,所以尽量避免无谓的同步控制。


参考链接:https://blog.csdn.net/zjy15203167987/article/details/82531772

参考链接:https://www.jianshu.com/p/3cfdf32bd37e

                

你可能感兴趣的:(Android,java,Synchronized)