一、synchronized简介

synchronized是关键字,用来实现同步锁,非公平锁,可重入锁

公平锁:
是按照锁申请的顺序来获取锁,线程直接进入同步队列中排队,队列中的第一个线程才能获得到锁。
非公平锁:
非公平锁是线程申请锁时,直接尝试加锁,获取不到才会进入到同步队列排队。如果此时该线程刚好获取到了锁,那么它不需要因为队列中有其他线程在排队而阻塞,省去了CPU唤醒该线程的开销。而对于已经在同步队列中的线程,仍然是按照先进先出的公平规则获取锁~

什么是可重入?
同一个线程可以反复获取锁多次,然后需要释放多次

它修饰的对象有以下几种:
  1. 修饰一个代码块,被修饰的代码块称为同步语句块,其作用的范围是大括号{}括起来的代码,作用的对象是调用这个代码块的对象;
  2. 修饰一个方法,被修饰的方法称为同步方法,其作用的范围是整个方法,作用的对象是调用这个方法的对象;
  3. 修改一个静态的方法,其作用的范围是整个静态方法,作用的对象是这个类的所有对象;
  4. 修改一个类,其作用的范围是synchronized后面括号括起来的部分,作用主的对象是这个类的所有对象。

二、锁升级过程

redission公平锁的使用场景_后端


redission公平锁的使用场景_开发语言_02

二、ReentrantLock

ReentrantLock是一个可重入的同步锁,可以通过设置参数决定使用公平锁和非公平锁。

ReentrantLock lock = new ReentrantLock(); //参数默认false,不公平锁
ReentrantLock lock = new ReentrantLock(true); //公平锁
lock.lock(); //如果被其它资源锁定,会在此等待锁释放,达到暂停的效果
try {
	//操作
} finally {
    lock.unlock();
}

尝试等待执行:

ReentrantLock lock = new ReentrantLock(true); //公平锁
try {
	if (lock.tryLock(5, TimeUnit.SECONDS)) {  	
		//如果已经被lock,尝试等待5s,看是否可以获得锁,如果5s后仍然无法获得锁则返回false继续执行
		try {
			//操作
		} finally {
			lock.unlock();
		}
	}
} catch (InterruptedException e) {
	e.printStackTrace(); //当前线程被中断时(interrupt),会抛InterruptedException                 
}

模拟三个线程:

redission公平锁的使用场景_java_03


使用ReentrantLock:

public class Test {
    public static void main(String[] args) {
        ReentrantLock lock = new ReentrantLock();

        new Thread(() -> {
        	System.out.println("A thread door");
            lock.lock();
            try{
                System.out.println("-----A thread come in");
                try {
                    TimeUnit.SECONDS.sleep(10);
                    System.out.println("=====A thread is over");
                }catch (Exception e) {
                    e.printStackTrace();
                }
            }finally {
                lock.unlock();
            }
        },"A").start();

        new Thread(() -> {
            System.out.println("B thread door");
            lock.lock();//因为A线程已经占有了锁,所以会被阻塞在这一步
            try{
                System.out.println("-----B thread come in");
            }finally {
                lock.unlock();
            }
        },"B").start();

        new Thread(() -> {
            System.out.println("C thread door");
            lock.lock();//因为A线程已经占有了锁,所以会被阻塞在这一步
            try{
                System.out.println("-----C thread come in");
            }finally {
                lock.unlock();
            }
        },"C").start();
    }
}

redission公平锁的使用场景_开发语言_04