锁——synchronized关键字

二、synchronized关键字加锁:

必须掌握知识点:

  • synchronized关键字底层原理:通过jvm指令,《深入理解jvm》,《并发编程艺术》page11
  • synchronized的几种加锁方式。
  • synchronized锁优化,不再是重量级了。
  • synchronized和reentrantlock的区别

https://mp.weixin.qq.com/s?__biz=Mzg2OTA0Njk0OA==&mid=2247484838&idx=1&sn=54b33b4c76e136efac09941b2dd346b3&source=41#wechat_redirect

(1)synchronized修饰普通方法:在修饰普通方法的时候,这个锁是当前实例对象,即对象锁。

  也就是说,这个锁只对当前的对象实例创建的线程有效,若我们在程序中创建多个对象实例,不同实例分别创建一个线程,这时候这些线程都能同时进到这个方法里,也就是说这个对象锁,只对当前实例线程有效,多个实例就无效了。

  如下代码,就是修饰普通方法,但是锁是无效的,因为这个已经是不同实例了。要想使锁有效,要保证线程的创建者同属于一个实例对象。

//锁失效
public class Demo1 { static int num = 0; public synchronized void m1(){ for(int i=0;i<10000;i++){ num++; } } public static void main(String[] args) throws InterruptedException { Thread t1 = new Thread(()->{Demo1 demo1 = new Demo1();demo1.m1();}); Thread t2 = new Thread(()->{Demo1 demo1 = new Demo1();demo1.m1();}); Thread t3 = new Thread(()->{Demo1 demo1 = new Demo1();demo1.m1();});
t1.start(); t2.start(); t3.start(); t1.join(); t2.join(); t3.join(); System.out.println(num); } }
//锁有效
public class Demo1 { static int num = 0; public synchronized void m1(){ for(int i=0;i<10000;i++){ num++; } } public static void main(String[] args) throws InterruptedException { Demo1 demo1 = new Demo1(); Thread t1 = new Thread(()->demo1.m1()); Thread t2 = new Thread(()->demo1.m1()); Thread t3 = new Thread(()->demo1.m1()); t1.start(); t2.start(); t3.start(); t1.join(); t2.join(); t3.join(); System.out.println(num); } }

(2)synchronized修饰静态方法:锁是当前类Class对象,即类锁,全局锁。

  也就是说,这个锁对于不同实例创建的线程均有效。

public class Demo1 {
    static int num = 0;

    public synchronized static void  m1(){
        for(int i=0;i<10000;i++){
            num++;
        }
    }

    public static class T1 extends Thread{
        @Override
        public void run() {
            Demo1.m1();
        }
    }

    public static void main(String[] args) throws InterruptedException {
        T1 t1 = new T1();
        T1 t2 = new T1();
        T1 t3 = new T1();

        t1.start();
        t2.start();
        t3.start();

        t1.join();
        t2.join();
        t3.join();

        System.out.println(num);
    }
}

(3)同步代码块,synchronize(class对象){}:这时候这个锁是全局锁,对不同实例创建的线程依然有效。

public class Demo1 {
    static int num = 0;

    public  void  m1(){
        // class对象锁
        synchronized (Demo1.class){
            for(int i=0;i<10000;i++){
                num++;
            }
        }
    }

    public static void main(String[] args) throws InterruptedException {

        Thread t1 = new Thread(()->{Demo1 demo1 = new Demo1();demo1.m1();});
        Thread t2 = new Thread(()->{Demo1 demo1 = new Demo1();demo1.m1();});
        Thread t3 = new Thread(()->{Demo1 demo1 = new Demo1();demo1.m1();});

        t1.start();
        t2.start();
        t3.start();

        t1.join();
        t2.join();
        t3.join();

        System.out.println(num);
    }
}

(4)同步代码块,synchronize(this){}:传入的对象为当前实例的时候,这时候就是对象锁,锁只对当前实例创建的线程有效。

public class Demo1 {
    static int num = 0;

    public  void  m1(){
        // class对象锁
        synchronized (this){
            for(int i=0;i<10000;i++){
                num++;
            }
        }
    }

    public static void main(String[] args) throws InterruptedException {

        Demo1 demo1 = new Demo1();

        Thread t1 = new Thread(()->demo1.m1());
        Thread t2 = new Thread(()->demo1.m1());
        Thread t3 = new Thread(()->demo1.m1());

        t1.start();
        t2.start();
        t3.start();

        t1.join();
        t2.join();
        t3.join();

        System.out.println(num);
    }
}

参考博客:https://www.cnblogs.com/chenshy/p/11658691.html 这个写的比较深入,比较好

参考博客:https://blog.csdn.net/x1107761900/article/details/88713549

posted @ 2021-01-18 22:57  guoyu1  阅读(308)  评论(0编辑  收藏  举报