轉自:https://m.jb51.net/article/154421.htmjava
1 悲觀鎖redis
執行操做前假設當前的操做確定(或有很大概率)會被打斷(悲觀)。基於這個假設,咱們在作操做前就會把相關資源鎖定,不容許本身執行期間有其餘操做干擾。緩存
Redis不支持悲觀鎖。Redis做爲緩存服務器使用時,以讀操做爲主,不多寫操做,相應的操做被打斷的概率較少。不採用悲觀鎖是爲了防止下降性能。服務器
2 樂觀鎖分佈式
執行操做前假設當前操做不會被打斷(樂觀)。基於這個假設,咱們在作操做前不會鎖定資源,萬一發生了其餘操做的干擾,那麼本次操做將被放棄。工具
3. Redis中的鎖策略性能
Redis採用了樂觀鎖策略(經過watch操做)。樂觀鎖支持讀操做,適用於多讀少寫的狀況!
在事務中,能夠經過watch命令來加鎖;使用 UNWATCH能夠取消加鎖;
若是在事務以前,執行了WATCH(加鎖),那麼執行EXEC 命令或 DISCARD 命令後,鎖對自動釋放,即不須要再執行 UNWATCH 了學習
例子測試
redis鎖工具類this
package com.fly.lock; import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisPool; import redis.clients.jedis.JedisPoolConfig; public class RedisLock { //初始化redis池 private static JedisPoolConfig config; private static JedisPool pool; static { config = new JedisPoolConfig(); config.setMaxTotal(30); config.setMaxIdle(10); pool = new JedisPool(config, "192.168.233.200", 6379); } /** * 給target上鎖 * @param target **/ public static void lock(Object target) { //獲取jedis Jedis jedis = pool.getResource(); //result接收setnx的返回值,初始值爲0 Long result= 0L; while (result < 1) { //若是target在redis中已經存在,則返回0;不然,在redis中設置target鍵值對,並返回1 result = jedis.setnx(target.getClass().getName() + target.hashCode(), Thread.currentThread().getName()); } jedis.close(); } /** * 給target解鎖 * @param target **/ public static void unLock(Object target) { Jedis jedis = pool.getResource(); //刪除redis中target對象的鍵值對 Long del = jedis.del(target.getClass().getName() + target.hashCode()); jedis.close(); } /** * 嘗試給target上鎖,若是鎖成功返回true,若是鎖失敗返回false * @param target * @return **/ public static boolean tryLock(Object target) { Jedis jedis = pool.getResource(); Long row = jedis.setnx(target.getClass().getName() + target.hashCode(), "true"); jedis.close(); if (row > 0) { return true; } return false; } }
測試類
package com.fly.test; import com.fly.lock.RedisLock; class Task { public void doTask() { //上鎖 RedisLock.lock(this); System.out.println("當前線程: " + Thread.currentThread().getName()); System.out.println("開始執行: " + this.hashCode()); try { System.out.println("doing..."); Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("完成: " + this.hashCode()); //解鎖 RedisLock.unLock(this); } } public class Demo { public static void main(String[] args) { Task task = new Task(); Thread[] threads = new Thread[5]; for (Thread thread : threads) { thread = new Thread(()->{ task.doTask(); }); thread.start(); } } }
輸出結果:
----------------------------------------------
當前線程: Thread-0
開始執行: 2081499965
doing...
完成: 2081499965
----------------------------------------------
當前線程: Thread-2
開始執行: 2081499965
doing...
完成: 2081499965
----------------------------------------------
當前線程: Thread-1
開始執行: 2081499965
doing...
完成: 2081499965
----------------------------------------------
當前線程: Thread-4
開始執行: 2081499965
doing...
完成: 2081499965
----------------------------------------------
當前線程: Thread-3
開始執行: 2081499965
doing...
完成: 2081499965
去掉redis鎖後,執行結果:
----------------------------------------------
----------------------------------------------
當前線程: Thread-2
開始執行: 1926683415
----------------------------------------------
當前線程: Thread-1
doing...
當前線程: Thread-0
----------------------------------------------
當前線程: Thread-3
開始執行: 1926683415
doing...
開始執行: 1926683415
doing...
----------------------------------------------
開始執行: 1926683415
doing...
當前線程: Thread-4
開始執行: 1926683415
doing...
完成: 1926683415
完成: 1926683415
完成: 1926683415
完成: 1926683415
完成: 1926683415
Process finished with exit code 0
利用redis這個性質,能夠實現分佈式鎖,固然設計必定複雜一些!
總結
以上就是這篇文章的所有內容了,但願本文的內容對你們的學習或者工做具備必定的參考學習價值,謝謝你們對腳本之家的支持。若是你想了解更多相關內容請查看下面相關連接