synchronized关键字的作用
JVM会使用monitor来加锁和解锁,保证了某个时刻只有一个线程执行同步块代码,从而保证了线程安全,同时具有可重入性和不可中断性。
synchronized的四种用法:
1第一种:在实例方法前加上synchronized关键字,锁的对象是该类的一个实例化的对象,不同对象同时调用这个方法会并发同时执行,只有是同一个实例化对象时,才会发生线程等待的情况。
public synchronized void add(){
int a=0;
a++;
}
2.第二种 :在静态方法之前加上synchronized关键字,锁的对象时这个class对象,一个class只有一个class对象。
public synchronized static void remove(){
int a=0;
a--;
}
3.第三种: 以代码的形式,给类的实例化对象加锁
synchronized (this){
}
4第四种:以代码块的形式,给class对象加锁
synchronized (Class.class){
}
前两种是以方法的形式同步,后两种以代码块的形式同步。第一种和第三种锁的对象是该类的一个实例化对象,第二种和第四种锁的对象是class的对象
性质
可重入性:指当前对象在获得锁之后可以再次获得锁
public class SynaTest {
int a=0;
public synchronized void add(){
a++;
remove();
}
public synchronized void remove(){
a--;
}
public static void main(String[] args){
SynaTest synaTest=new SynaTest();
Thread thread = new Thread(){
public void run(){
synaTest.add();
}
};
thread.start();
System.out.print(synaTest.a);
}
}
//输入结果
0
Process finished with exit code 0
在调用add()方法时,又调用了remov()方法,最终输出结果为0。这样的好处时避免死锁,假如一个线程在调用add方法时,他已经获得了当前对象的锁进入add()方法后,调用remove方法,此时要重新获得该对象的锁,可是当前对象的锁还没有释放,就会一直等待下去。
不可中断性:指同步代码执行时,其他线程无法打断他,即使等级比他高的线程。这是synchronized关键字的一个缺点,加锁和解锁方式单一。可以用lock来代替synchronized关键字,lock加锁和解锁的方式比较灵活。
专家建议:并发程序的应首先考虑使用juc中已经封装好的工具,然后才是synchronized关键字,最后时lock,虽然lock灵活,但是对于并发经验少的程序员来说,容易出现意想不到的结果比如死锁等。
java 中的锁 -- 偏向锁、轻量级锁、自旋锁、重量级锁:https://blog.youkuaiyun.com/zqz_zqz/article/details/70233767#commentBox