redis实战教程(一)-分布式锁

主要用到setnx函数,原理如下:

命令格式

SETNX key value

将 key 的值设为 value,当且仅当 key 不存在。
若给定的 key 已经存在,则 SETNX 不做任何动作。
SETNX 是SET if Not eXists的简写。

返回值

返回整数,具体为
- 1,当 key 的值被设置
- 0,当 key 的值没被设置

例子

redis> SETNX mykey “hello”
(integer) 1
redis> SETNX mykey “hello”
(integer) 0
redis> GET mykey
“hello”
redis>

使用SETNX实现分布式锁

多个进程执行以下Redis命令:

SETNX lock.foo <current Unix time + lock timeout + 1>

如果 SETNX 返回1,说明该进程获得锁,SETNX将键 lock.foo 的值设置为锁的超时时间(当前时间 + 锁的有效时间)。
如果 SETNX 返回0,说明其他进程已经获得了锁,进程不能进入临界区。进程可以在一个循环中不断地尝试 SETNX 操作,以获得锁。



package net.csdn.redis;

import java.util.concurrent.TimeUnit;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

public class RedisDemo {
	private static JedisPool pool;
	private static String redisServerIp = "192.168.0.43";
	private static String redisPassord = "MMHlive2016";
	private static int connectTimeout = 20 * 1000;// 2秒
	
	/**
	 * 建立连接池 真实环境,一般把配置参数缺抽取出来。
	 * 
	 */
	private static void createJedisPool() {

		// 建立连接池配置参数
		JedisPoolConfig config = new JedisPoolConfig();

		// 设置最大连接数
		config.setMaxActive(10000);

		// 设置最大阻塞时间,记住是毫秒数milliseconds
		config.setMaxWait(connectTimeout);

		// 设置空间连接
		config.setMaxIdle(500);
		// 创建连接池
		pool = new JedisPool(config, redisServerIp, 6379, connectTimeout, redisPassord);
	}

	/**
	 * 在多线程环境同步初始化
	 */
	private static synchronized void poolInit() {
		if (pool == null)
			createJedisPool();
	}

	/**
	 * 获取一个jedis 对象
	 * 
	 * @return
	 */
	private static Jedis getJedis() {
		if (pool == null)
			poolInit();
		return pool.getResource();
	}

	/**
	 * 归还一个连接
	 * 
	 * @param jedis
	 */
	private static void returnRes(Jedis jedis) {
		pool.returnResource(jedis);
	}
	public static long setnx(String key, String val, int timeout) {
		Jedis jedis = getJedis();
		long rst = jedis.setnx(key, val);
		if (rst == 1) {
			jedis.expire(key, timeout);
		}
		returnRes(jedis);
		return rst;
	}
	public static long delete(String sessionId) {
		Jedis jedis = getJedis();
		Long rst = jedis.del(sessionId);
		returnRes(jedis);
		return rst;
	}
	public static boolean tryLock(String key, int timeout) {
		long nano = System.nanoTime();
		do {
			 
			Long i = setnx(key, key, timeout);
//			System.out.println(i);
			if (i == 1) {
				System.out.println(Thread.currentThread().getName()+":获得锁");
				return true;
			}
			if (timeout == 0) {
				break;
			}
			try {
				Thread.sleep(300);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			if((System.nanoTime() - nano) > TimeUnit.SECONDS.toNanos(timeout)){
				break;
			}
		} while (true);

		throw new RuntimeException("获取[" + key + "]锁超时");
		
	}
	
	
	public static void main(String[] args) throws Exception {
		String key="wweerrt";
		delete(key);
		int timeout=1000000;
		new Thread(()->{
			System.out.println(Thread.currentThread().getName()+":开始加锁");
			tryLock(key, timeout);
		}) .start();
		new Thread(()->{
			System.out.println(Thread.currentThread().getName()+":开始加锁");
			tryLock(key, timeout);
		}) .start();
		
		Thread.sleep(100000L);
	}
}

控制台输出:
Thread-1:开始加锁
Thread-2:开始加锁
Thread-1:获得锁



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值