synchronized锁
1.什么是synchronized锁
(1)synchronized是⼀种互斥锁
⼀次只能允许⼀个线程进⼊被锁住的代码块
(2)synchronized是⼀种内置锁/监视器锁
Java中每个对象都有⼀个内置锁(监视器,也可以理解成锁标记),⽽synchronized就是使⽤对象的内置锁(监视器)来将代码块(⽅法)锁定的! (锁的是对象,但我们同步的是⽅法/代码块)
synchronized保证了线程的原⼦性。(被保护的代码块是⼀次被执⾏的,没有任何线程会同时访问)。
synchronized还保证了可见性。(当执⾏完synchronized之后,修改后的变量对其他的线程是可见的)。
2.synchronized关键字的使用
(1)修饰普通⽅法
⽤的锁是Test对象(内置锁)
public class Test {
// 修饰普通⽅法,此时⽤的锁是Test对象(内置锁)
public synchronized void test() {
// doSomething
}
}
(2)修饰代码块
⽤的锁是Test对象(内置锁)
public class Test {
// 使⽤object作为锁(任何对象都有对应的锁标记,object也不例外)
private Object object = new Object();
public void test() {
// 修饰代码块,此时⽤的锁是⾃⼰创建的锁Object
synchronized (object){
// doSomething
}
}
}
(3)修饰静态⽅法
获取到的是类锁(类的字节码⽂件对象):Test.class
public class Test {
// 修饰静态⽅法代码块,静态⽅法属于类⽅法,它属于这个类,获取到的锁是属于类的锁(类的字节码⽂件对象)-->Test.class
public static synchronized void test() {
// doSomething
}
}
3.类锁与对象锁
synchronized修饰静态方法获取的是类锁(类的字节码文件对象),synchronized修饰普通方法或代码块获取的是对象锁。
获取了类锁的线程和获取了对象锁的线程是不冲突的
4.synchronized加锁操作的关注点
(1)对哪一个对象加锁 一个对象只有一把锁
(2)只有同一个对象,才会有同步互斥的作用(多线程线程安全的三大特性都能满足)
(3)对于synchronized内的代码来说,在同一个时间点,只有一个线程在运行(没有并发、并行)
(4)运行的线程数量越多,性能下降越快(归还对象锁的时候,就有越多的线程不停的在被唤醒、阻塞状态切换)
(5)同步代码执行时间越短,性能下降也较快
5.释放锁
(1)当⽅法(代码块)执⾏完毕后会⾃动释放锁,不需要做任何的操作。
(2)当⼀个线程执⾏的代码出现异常时,其所持有的锁会⾃动释放。