当前位置:   article > 正文

redis分布式锁实现_rediscallback

rediscallback

单体应用多线程锁

使用synchronized关键字或ReentrantLock类来保证线程的顺序执行

个别场景使用JDK1.5之后提供的大量原子类AtomicInteger(基于CAS的乐观锁)

测试锁模拟并发可使用闭锁:CountDownLatch类对象模拟

ReentrantLock的公平锁和非公平锁机制

       ReentrantLock有两个构造方法,默认的构造方法中,sync = new NonfairSync();我们可以从字面意思看出它是一个非公平锁。再看看第二个构造方法,它需要传入一个参数,参数是一个布尔型,true是公平锁,false是非公平锁。从上面的源码我们可以看出sync有两个实现类,分别是FairSyncNonfairSync;

  唯一的不同之处在于!hasQueuedPredecessors()这个方法,很明显这个方法是一个队列,由此可以推断,公平锁是将所有的线程放在一个队列中,一个线程执行完成后,从队列中取出下一个线程,而非公平锁则没有这个队列。这些都是公平锁与非公平锁底层的实现原理。

  1. //基于原子类(乐观锁)
  2. public class Test {
  3. private AtomicInteger i = new AtomicInteger(0);
  4. public static void main(String[] args) {
  5. Test test = new Test();
  6. ExecutorService es = Executors.newFixedThreadPool(50);
  7. CountDownLatch cdl = new CountDownLatch(5000);
  8. for (int i = 0;i < 5000; i++){
  9. es.execute(()->{
  10. test.i.incrementAndGet();
  11. cdl.countDown();
  12. });
  13. }
  14. es.shutdown();
  15. try {
  16. cdl.await();
  17. System.out.println("执行完成后,i="+test.i);
  18. } catch (InterruptedException e) {
  19. e.printStackTrace();
  20. }
  21. }
  22. }
  23. //基于synchronized (悲观锁)
  24. //使用CountDownLatch模拟并发
  25. public class Test {
  26. private int i=0;
  27. public static void main(String[] args) {
  28. Test test = new Test();
  29. ExecutorService es = Executors.newFixedThreadPool(50);
  30. CountDownLatch cdl = new CountDownLatch(5000);
  31. for (int i = 0;i < 5000; i++){
  32. es.execute(()->{
  33. //修改部分 开始
  34. synchronized (test){
  35. test.i++;
  36. }
  37. //修改部分 结束
  38. cdl.countDown();
  39. });
  40. }
  41. es.shutdown();
  42. try {
  43. cdl.await();
  44. System.out.println("执行完成后,i="+test.i);
  45. } catch (InterruptedException e) {
  46. e.printStackTrace();
  47. }
  48. }
  49. }
  50. //基于ReentrantLock(悲观锁)
  51. //使用CountDownLatch模拟并发
  52. public class test {
  53. private int i=0;
  54. Lock lock = new ReentrantLock();
  55. public static void main(String[] args) {
  56. test test = new test();
  57. //线程池:50个线程
  58. ExecutorService es = Executors.newFixedThreadPool(50);
  59. //闭锁
  60. CountDownLatch cdl = new CountDownLatch(5000);
  61. for (int i = 0;i < 5000; i++){
  62. es.execute(()->{
  63. test.lock.lock();
  64. test.i++;
  65. test.lock.unlock();
  66. cdl.countDown();
  67. });
  68. }
  69. es.shutdown();
  70. try {
  71. //等待5000个任务执行完成后,打印出执行结果
  72. cdl.await();
  73. System.out.println("执行完成后,i="+test.i);
  74. } catch (InterruptedException e) {
  75. e.printStackTrace();
  76. }
  77. }
  78. }

分布式多线程锁

实现方式,一半基于第三方,如:数据库加锁,redis的单线程特性,zk,redisson分布式锁

1.基于mysql数据库sql特性   select.....for update  行锁(排它锁),高并发不适用,数据库压力大

2.redis分布式锁,代码示例如下:

  1. //公共类,锁工具
  2. //AutoCloseable 自动关闭资源
  3. @Slf4j
  4. public class RedisLock implements AutoCloseable {
  5. private RedisTemplate redisTemplate;
  6. private String key;
  7. private String value;
  8. //单位:秒
  9. private int expireTime;
  10. public RedisLock(RedisTemplate redisTemplate,String key,int expireTime){
  11. this.redisTemplate = redisTemplate;
  12. this.key = key;
  13. this.expireTime=expireTime;
  14. this.value = UUID.randomUUID().toString();
  15. }
  16. /**
  17. * 获取分布式锁
  18. * @return
  19. */
  20. public boolean getLock(){
  21. RedisCallback<Boolean> redisCallback = connection -> {
  22. //设置NX
  23. RedisStringCommands.SetOption setOption = RedisStringCommands.SetOption.ifAbsent();
  24. //设置过期时间
  25. Expiration expiration = Expiration.seconds(expireTime);
  26. //序列化key
  27. byte[] redisKey = redisTemplate.getKeySerializer().serialize(key);
  28. //序列化value
  29. byte[] redisValue = redisTemplate.getValueSerializer().serialize(value);
  30. //执行setnx操作
  31. Boolean result = connection.set(redisKey, redisValue, expiration, setOption);
  32. return result;
  33. };
  34. //获取分布式锁
  35. Boolean lock = (Boolean)redisTemplate.execute(redisCallback);
  36. return lock;
  37. }
  38. public boolean unLock() {
  39. String script = "if redis.call(\"get\",KEYS[1]) == ARGV[1] then\n" +
  40. " return redis.call(\"del\",KEYS[1])\n" +
  41. "else\n" +
  42. " return 0\n" +
  43. "end";
  44. RedisScript<Boolean> redisScript = RedisScript.of(script,Boolean.class);
  45. List<String> keys = Arrays.asList(key);
  46. Boolean result = (Boolean)redisTemplate.execute(redisScript, keys, value);
  47. log.info("释放锁的结果:"+result);
  48. return result;
  49. }
  50. @Override
  51. public void close() throws Exception {
  52. unLock();
  53. }
  54. }
  55. //可起多应用多线程测试
  56. //try(){}catch(){} 新特性
  57. //AutoCloseable 自动关闭资源
  58. @Service
  59. @Slf4j
  60. public class SchedulerService {
  61. @Autowired
  62. private RedisTemplate redisTemplate;
  63. @Scheduled(cron = "0/5 * * * * ?")
  64. public void sendSms(){
  65. try(RedisLock redisLock = new RedisLock(redisTemplate,"autoSms",30)) {
  66. if (redisLock.getLock()){
  67. log.info("向138xxxxxxxx发送短信!");
  68. }
  69. } catch (Exception e) {
  70. e.printStackTrace();
  71. }
  72. }
  73. }

Redisson分布式锁

  1. //引入依赖jar包
  2. //<dependency>
  3. // <groupId>org.redisson</groupId>
  4. // <artifactId>redisson</artifactId>
  5. // <version>3.11.2</version>
  6. //</dependency>
  7. //<dependency>
  8. // <groupId>org.redisson</groupId>
  9. // <artifactId>redisson-spring-boot-starter</artifactId>
  10. // <version>3.17.0</version>
  11. //</dependency>
  12. //简单一个请求方法示例
  13. @RestController
  14. @Slf4j
  15. public class RedissonLockController {
  16. @Autowired
  17. private RedissonClient redisson;
  18. @RequestMapping("redissonLock")
  19. public String redissonLock() {
  20. //获取锁
  21. RLock rLock = redisson.getLock("order");
  22. log.info("我进入了方法!!");
  23. try {
  24. //加锁,设置过期时间
  25. rLock.lock(30, TimeUnit.SECONDS);
  26. log.info("我获得了锁!!!");
  27. Thread.sleep(10000);
  28. } catch (InterruptedException e) {
  29. e.printStackTrace();
  30. }finally {
  31. log.info("我释放了锁!!");
  32. rLock.unlock();
  33. }
  34. log.info("方法执行完成!!");
  35. return "方法执行完成!!";
  36. }
  37. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/不正经/article/detail/331478
推荐阅读
相关标签
  

闽ICP备14008679号