什么是公平锁,非公平锁,递归锁,独占锁(写锁),共享锁(读锁),自旋锁?

11 篇文章 0 订阅

1.公平锁,非公平锁

公平锁:就是很公平,在并发环境中,每个线程在获取时会先查看此锁维护的队列,如果为空,或者当前线程是等待队列的第一个就占有锁,否则就会加入到队列中,以后会按照FIFO的规则从队列中取到自己。


非公平锁:非公平锁比较粗鲁,上来就直接尝试占有锁,如果尝试失败,就再采用类似公平锁那种方式。

// 非公平锁
Lock lock = new ReentrantLock(); 

// 公平锁
Lock lock = new ReentrantLock(true);

Java ReentrantLock 而言,通过构造器函数指定该锁是否是公平锁,默认是非公平锁。非公平锁的优点在于吞吐量比公平锁大。

对于synchronized而言,也是一种非公平锁。


2.递归锁(可重入锁)

指的是同一线程外层函数获得锁后,内层递归函数仍能获取该锁的代码。在同一个线程在外层方法获取锁的时候,在进入内层方法会自动获取锁。
也就是说,线程可以进入任何一个它已经拥有的锁所同步的代码块。

ReentrantLock和synchronized就是典型的可重入锁。


3.自旋锁(spinlock)

是指尝试获取锁的线程不会立即阻塞,而是采用循环的方式去获取锁,这样的好处是嫌少线程上下文切换的消耗,缺点就是增加CPU的消耗

自定义字段锁,代码如下:

public class SpinlockDemo {
	
	private AtomicReference<Thread> atomicReference = new AtomicReference<Thread>(); 

	public void lock() {
		Thread thread = Thread.currentThread();
		do {
			
		} while (!atomicReference.compareAndSet(null, thread));
	}
	
	public void unlock() {
		atomicReference.set(null);
	}
	
	public static void main(String[] args) throws InterruptedException {
		SpinlockDemo spinlockDemo = new SpinlockDemo();
		
		new Thread(() -> {
			System.out.println("t1--->获取锁");
			spinlockDemo.lock();
			System.out.println("t1--->获取锁成功");
			try {
				System.out.println("t1--->");
				Thread.sleep(5 * 1000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			} finally {
				System.out.println("t1--->解锁");
				spinlockDemo.unlock();
				System.out.println("t1--->解锁成功");
			}
		}, "t1").start();
		
		
		Thread.sleep(1000);
		
		new Thread(() -> {
			System.out.println("t2--->获取锁");
			spinlockDemo.lock();
			System.out.println("t2--->获取锁成功");
			try {
				System.out.println("t2--->");
				Thread.sleep(1 * 1000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			} finally {
				System.out.println("t2--->解锁");
				spinlockDemo.unlock();
				System.out.println("t2--->解锁成功");
			}
		}, "t2").start();
		
	}
}

4. 读写锁

多个线程同事读一个资源类没有任何问题,所以为了满足并发量,读取共享资源应该可以同是进行。但是,如果有一个线程想去写共享资源,就不应该再有其他的线程可以对该资源进行读或者写。


读-读共存
读-写互斥
写-写互斥

class MyCache {
	
	private volatile Map<String, Object> map = new HashMap<>();
	
	private ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
	
	public void put(String key, Object value) {
		lock.writeLock().lock();
		try {
			System.out.println(Thread.currentThread().getName() + "\t正在写入:" + key);
			Thread.sleep(300);
			map.put(key, value);
			System.out.println(Thread.currentThread().getName() + "\t写入完成");
		} catch (InterruptedException e) {
			e.printStackTrace();
		} finally {
			lock.writeLock().unlock();
		}
	}
	
	public void get(String key) {
		lock.readLock().lock();
		try {
			System.out.println(Thread.currentThread().getName() + "\t正在读取:" + key);
			Thread.sleep(300);
			Object value = map.get(key);
			System.out.println(Thread.currentThread().getName() + "\t读取完成:" + value);
		} catch (InterruptedException e) {
			e.printStackTrace();
		} finally {
			lock.readLock().unlock();
		}
	}
	
}

public class ReadWriteLockDemo {

	public static void main(String[] args) {
		
		MyCache cache = new MyCache();
		
		for (int i = 0; i < 5; i++) {
			final String temp = String.valueOf(i);
			new Thread(() -> {
				cache.put(temp, temp);
			}, String.valueOf(i)).start(); 
		}
		
		for (int i = 0; i < 5; i++) {
			final String temp = String.valueOf(i);
			new Thread(() -> {
				cache.get(temp);
			}, String.valueOf(i)).start(); 
		}
		
	}
}

在这里插入图片描述

上面的结果没有按照顺序打印出来,可以看出,在读的过程中是异步的!!

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值