二、synchronized关键字加锁:
必须掌握知识点:
- synchronized关键字底层原理:通过jvm指令,深入理解jvm
- synchronized的几种加锁方式。
- synchronized锁优化,不再是重量级了。
- synchronized和reentrantlock的区别
(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