关于分布式锁

分布式锁

  • 所有服务可以去一个公共的地方**“占坑“**,可以去数据库,也可以去redis,当占坑成功后,其他服务会判断有没有坑位,若已经被占了,则等待坑位,等待可以采取自旋的方式。

  • redis命令: set k v NX

  • redisTemplate相关的api setIfAbsent()

  • 设置过期时间加锁成功 获取数据释放锁 [分布式下必须是Lua脚本删锁,不然会因为业务处理时间、网络延迟等等引起数据还没返回锁过期或者返回的过程中过期 然后把别人的锁删了]

  • **

redisson

定义: redis对于java实现的分布式框架

如何使用:

  1. 引入依赖

  2.     <dependency>
        <groupId>org.redisson</groupId>
        <artifactId>redisson</artifactId>
        <version>3.12.5</version>
    </dependency>
    
  3. 配置redisson:1.使用程序化配置 2.使用文本配置

  4. 这里采用程序化配置

	@Bean(destroyMethod="shutdown")
	public RedissonClient redisson() {
		Config config = new Config();
		config.useSingleServer().setAddress("redis://127.0.0.1:6379");
		RedissonClient redissonClient = Redisson.create(config);
		return redissonClient;
	}

使用时直接注入即可

 @Autowired
    RedissonClient redissonClient;

可重入锁(Reetrant Lock)

  • 假设有两个方法,分别为A、B,现在A方法里调用B方法,并且A B都想用锁,此时对A加可重入锁就代表拿到A的锁之后执行B相当于拿到了A、B的锁,可以不用等待就执行b方法

公平锁

  • 假设有多个线程,其中一个线程抢到了锁,执行完之后释放锁,默认是其他线程去抢这个锁,谁抢到了谁执行。公平锁是在释放锁之后,其他线程会按照请求的时间去有顺序的抢占锁。

读写锁

写锁存在,读锁要等写锁释放,
读锁是一个排它锁(互斥锁),在并发写锁的情况下,写锁需要排队,读锁是一个共享锁。
写加读 读需要等写锁释放才可读
读加写 写需要等读释放才可以写

闭锁

public String lockDoor() throws InterruptedException {
		RCountDownLatch door = redissonClient.getCountDownLatch("door");
		// 设置这里有5个人
		door.trySetCount(5);
		//等待闭锁都完成
		door.await();

		return "5个人全部通过了...";
	}

	@ResponseBody
	@GetMapping("/index/go/{id}")
	public String go(@PathVariable("id") Long id) throws InterruptedException {

		RCountDownLatch door = redissonClient.getCountDownLatch("door");
		// 每访问一次相当于出去一个人
		door.countDown();
		return id + "走了";
	}

信号量测试:

public String park() throws InterruptedException {

		RSemaphore park = redissonClient.getSemaphore("park");
		//阻塞方法,获取不到信号量会一直阻塞
		park.acquire();
		//非阻塞方法,过了一定时间获取不到信号量会返回false
		boolean acquire = park.tryAcquire();
		return "获取车位 =>" + acquire;
	}

	/**
	 * 尝试获取车位
	 */
	@ResponseBody
	@GetMapping("/index/go/park")
	public String goPark() {

		RSemaphore park = redissonClient.getSemaphore("park");
		park.release();
		return "ok => 车位+1";
	}
上一篇:数据库从零开始的学习day01


下一篇:c#多线程问题