二、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