Java锁浅析

一、自旋锁:
一、公平锁和非公平锁

(一)公平锁:获取锁的顺序是按照阻塞的顺序来获取的,先到先得,先进先出
关于公平锁实例:
1、锁的初始化类

public class ServiceLock {
  private ReentrantLock lock;

  public ServiceLock(boolean isFair) {
      super();
      lock = new ReentrantLock(isFair);
  }

  public void serviceMethod() {
      try {
          lock.lock();
          System.out.println("ThreadName=" + Thread.currentThread().getName()+ "获取锁定");
      } finally {
          lock.unlock();
      }
  }

2、实现公平锁

public class ReentrantLockTest {

  public static void main(String[] args) {
      //这里我们对Service传递一个true,表示我们初始化ReentrantLock为公平锁
      final ServiceLock service = new ServiceLock(true);
      Runnable runnable = new Runnable() {

          @Override
          public void run() {
              System.out.println("❤线程" + Thread.currentThread().getName()+ "运行了");
              service.serviceMethod();
          }
      };
      Thread[] threadArray = new Thread[10];
      for(int i = 0; i<10;i++) {
          threadArray[i] = new Thread(runnable);
      }
      for (int i = 0; i < 10; i++) {
              threadArray[i].start();
      }
  }

3、我们来看看执行结果:
从结果上来看印证了公平锁的理论,当线程运行到获取锁的位置的时候,没有拿到锁的线程则阻塞着,当前面一个线程释放锁后,先被阻塞的线程先获得锁


(二)非公平锁:执行到获取锁的时候被阻塞,不论是什么时候回来的,随机分配锁
1、这里我们只需要将final ServiceLock service = new ServiceLock(false);初始化的时候用false,就可以实现非公平锁,看看代码:

public class ReentrantLockTest {

    public static void main(String[] args) {
        //这里我们对Service传递一个false,表示我们初始化ReentrantLock为非公平锁
        final ServiceLock service = new ServiceLock(false);
        Runnable runnable = new Runnable() {

            @Override
            public void run() {
                System.out.println("❤线程" + Thread.currentThread().getName()+ "运行了");
                service.serviceMethod();
            }
        };
        Thread[] threadArray = new Thread[10];
        for(int i = 0; i<10;i++) {
            threadArray[i] = new Thread(runnable);
        }
        for (int i = 0; i < 10; i++) {
                threadArray[i].start();
        }
    }

2、我们来看看执行结果:
可以看出运行的顺序和获取锁的顺序没有关系,这样就产生了非公平锁


三、可重入锁和不可重入锁:

(一) 可重入锁

可重入锁

(二)不可重入锁
不可重入锁

三、独享锁和共享锁:

(一)独享锁

  • 只能一个线程拥有该锁,这个锁就是独享锁
  • 举例:ReentrantLock和Synchronized都是独享锁

(二)共享锁

  • 可以多个线程获取到锁,这个锁就是共享锁
  • 举例:ReadWriteLock其是读锁的时候是共享锁,是写锁的时候是独享锁


    方法
四、互斥锁和读写锁

互斥锁是独享锁的一种实现,就是当一个线程持有锁的时候,其他的线程需要等待,ReentrantLock就是它的应用
读写锁是共享锁的一种实现,ReadWriteLock当为读锁的时候就是共享锁,为写锁的时候就是独享锁

五、分段锁

分段锁是一种锁的设计,不是指某种锁。
在JDK1.7中concurrentHashMap就使用了分段锁这种设计,concurrentHashMap和JDK1.7中的hashmap结构大致是一样的,而在concurrentHashMap中每个数组元素对应的链表上用Segment加锁,保存了数据添加的安全,Segment实现的是ReentrantLock。


Segment
五、悲观锁和乐观锁

这两种锁不是值某种具体类型的锁,而是指站在看待锁的不同角度。
悲观锁:认为在多线程操作共享数据的时候,不管线程会不会修改该数据,都会认为会被修改,这样悲观锁就会对共享数据采取加锁的形式,不加锁肯定是不安全的。
乐观锁:认为在多线程操作共享数据的时候,线程是不会修改数据的,每次获取数据的时候,都不会担心数据被修改,所以每次获取数据的时候都不会进行加锁,但是在更新数据的时候需要判断该数据是否被别人修改过。如果数据被其他线程修改,则不进行数据更新,如果数据没有被其他线程修改,则进行数据更新。由于数据没有进行加锁,期间该数据可以被其他线程进行读写操作。可以采用CAS原子操作实现!

六、偏向锁/轻量级锁/重量级锁

待续.......

你可能感兴趣的:(Java锁浅析)