这是我参与 8 月更文挑战的第 9 天,活动详情查看: 8月更文挑战
Java常见的锁
1.公平锁
公平锁就是很公平,在并发环境中,每个线程在获取锁时会先查看此锁维护的等待队列,如果为空,或者当前线程是等待队列的第一个,就占有锁,否则就会加入到等待队列中,以后会按照FIFO的规则从队列中取到自己。
2.非公平锁
非公平锁比较粗鲁,上来就直接尝试占有锁,如果尝试失败,就再采用公平锁那种方式。
3.可重入锁
指的是同一线程外层函数获得锁之后,内层递归函数仍然获取该锁的代码,在同一个线程在外层方法获取锁的时候,在进入内层方法会自动获取锁。也即是说,线程可以进入任何一个它已经拥有的锁所同步着的代码块。
4.代码的实现
4.1 公平锁和非公平锁的实例
/**
* Creates an instance of {@code ReentrantLock}.
* This is equivalent to using {@code ReentrantLock(false)}.
*/
public ReentrantLock() {
sync = new NonfairSync();
}
/**
* Creates an instance of {@code ReentrantLock} with the
* given fairness policy.
*
* @param fair {@code true} if this lock should use a fair ordering policy
*/
public ReentrantLock(boolean fair) {
sync = fair ? new FairSync() : new NonfairSync();
}
上面的源码表示,当ReentranLock创建的时候不传参数值,则默认是非公平锁;传入true则为公平锁。
4.2 可重入锁实例
Java的ReentrantLock和Synchronized都属于可重入锁。
package JUC;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* @Author MingJian_Zhu
* @Date 2021/8/12 17:38
*/
public class LockSample {
public static void main(String[] args) {
phone phone = new phone();
Thread thread3 = new Thread(phone);
Thread thread4 = new Thread(phone);
thread3.start();
thread4.start();
}
}
class phone implements Runnable{
Lock lock = new ReentrantLock(true);
@Override
public void run() {
get();
}
private void get() {
lock.lock();
try{
System.out.println(Thread.currentThread().getName()+"\t invoke get()");
set();
}finally{
lock.unlock();
}
}
private void set() {
lock.lock();
try{
System.out.println(Thread.currentThread().getName()+"\t invoke get()");
}finally{
lock.unlock();
}
}
}
上面的代码中,在两个线程t3,t4下,调用的get方法里面的set方法,两个方法都是用的是同一个锁。可重入锁的意思是在get方法的最外面一层已经加锁了,然后再次调用get方法的同步方法set的时候,set不需要获取新的锁就可以贝访问,因为在get方法的中已经获取到锁,set方法啊和get方法用的是同一把锁。上面代码的运行结果如下: