java并发编程:锁的相关概念介绍

理解同步,最好先把java中锁相关的概念弄清楚,有助于我们更好的去理解、学习同步。java语言中与锁有关的几个概念主要是:可重入锁、读写锁、可中断锁、公平锁

一、可重入锁

synchronized和ReentrantLock都属于可重入锁,当前加锁的程序调用了一个持有当前锁对象的子程序不会发生阻塞,代码如下

public synchronized void method2(){
    System.out.println("method2");
}
public synchronized void method1(){
    System.out.println("method1");
    method2();
}

执行method1()方法,获取锁,然后又调用同步方法method2(),这个时候线程不需要申请method2()的锁,可以直接执行

如果synchronized不具备可重入性,线程A持有对象锁,进入method1方法,这个时候就要重新申请锁,但是这个锁其实就是线程A进入method1方法持有的锁,这样的话,线程A会一直等待一个永远获取不到的锁,所以synchronized和Lock都具备可重入性

二、读写锁

读写锁是将对一个资源的访问分成了两个锁:读锁和写锁

读写锁中、读读不互斥、只有涉及到写锁才互斥

ReadWriteLock是读写锁的根接口,实现类是ReentrantReadWriteLock(他们并没有实现Lock接口)

通过readLock()获取读锁、writeLock()获取写锁

三、可中断锁

就是可以响应中断的锁。synchronized属于不可中断锁,Lock则是可中断锁

如果线程A正在执行锁包住的代码,线程B等待获取该锁,有可能等待时间太长,线程B想去做别的事,我们可以让他中断自己或者在别的线程中断他。lock类使用lockInterruptibly()方法来实现可中断性,代码如下:

package com.xhy.lock;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class LockInterruptTest {

    private Lock lock = new ReentrantLock();

    public static void main(String[] args) {
        LockInterruptTest test = new LockInterruptTest();
        MyThread myThread1 = new MyThread(test);
        MyThread myThread2 = new MyThread(test);
        myThread1.start();
        myThread2.start();
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        myThread2.interrupt();
     // 处于等待中的线程2可以被正常终端(只有在调用lockInterruptibly()方法的情况下) } public void insert() throws InterruptedException { lock.lockInterruptibly(); // lock.lock(); try { System.out.println(Thread.currentThread().getName() + "获得了锁"); while (true){ } }finally { System.out.println(Thread.currentThread().getName() + "执行了finally"); lock.unlock(); System.out.println(Thread.currentThread().getName() + "释放了锁"); } } } class MyThread extends Thread{ private LockInterruptTest test; public MyThread(LockInterruptTest test){ this.test = test; } @Override public void run() { try { test.insert(); } catch (InterruptedException e) { System.out.println(Thread.currentThread().getName() + "中断"); } } }

运行结果如下

四、公平锁

公平锁就是排队来获取锁,这个队是请求的顺序,不能抢占。非公平锁不能保证获取锁的顺序是按照请求锁的顺序来的。这样可能有的线程很难获取到锁,或者永远获取不到,哈哈

synchronized属于非公平锁,对ReentrantLock和ReentrantReadWriteLock,它们默认情况下也不是公平锁,通过构造方法可以指定,代码如下:

/**
 * 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();
}
/**
 * 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();
}

它们里面定义了两个静态内部类,一个是NoFailSync,一个是FairSync,分别用来实现公平与否

 

原文地址:https://www.cnblogs.com/xhy-shine/p/10785645.html