基于Mysql实现锁机制

1 ReentrantLock

它是一个可重入锁,即一个线程可重复加锁,即当前线程获取该锁再次获取不会被阻塞。获得几次锁,解锁也要解几次。
它有两种实现,公平锁和非公平锁。

  • 公平锁:锁的获取顺序就应该符合请求上的绝对时间顺序
  • 非公平锁:不按请求的时间,谁抢到就是谁的

默认实现的为非公平锁,因为公平锁为了保证时间上的绝对顺序,需要频繁的上下文切换,而非公平锁会降低一定的上下文切换,降低性能开销。

//创建一个公平锁
Lock lock = new ReentrantLock(true);

2. 通过MySQL的GET_LOCK函数实现

获得锁

GET_LOCK(str,timeout)

根据字符串str 得到一个锁,超时为timeout 秒。若成功得到锁,则返回 1,若操作超时则返回0 ,当它获得锁之后,后面相同str的再获取这把锁就会一直等待,当超过timeout,就会返回0

释放锁

RELEASE_LOCK(str);

释放str这把锁,当连接中断后,这把锁也会释放的

使用

获取锁
SELECT GET_LOCK("pibigstar",10);

释放锁
SELECT RELEASE_LOCK(“pibigstar”);

3 通过MySQL行级锁进行实现

原理很简单,我们插入数据的时候都是只能插入一个唯一主键,如果有一个线程插入了,那么其他线程都不能插入了。

插入实体

package com.pibigstar.domain;

import javax.persistence.Entity;
import javax.persistence.Id;

@Entity
public class Mysql {
	@Id
	private int id;
	public Mysql(int id) {
		this.id = id;
	}
	//setter、getter方法

}

dao层:使用jpa

package com.pibigstar.dao;

import org.springframework.data.jpa.repository.JpaRepository;

import com.pibigstar.domain.Mysql;

public interface MysqlLockDao extends JpaRepository<Mysql, Integer>{

}

具体实现

package com.pibigstar.utils;

import java.util.Random;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import org.springframework.beans.factory.annotation.Autowired;
import com.pibigstar.dao.MysqlLockDao;
import com.pibigstar.domain.Mysql;

/**
 * 基于mysql实现可重入锁
 * @author pibigstar
 *
 */
public class MysqlLock implements Lock{

	@Autowired
	private MysqlLockDao mysqlLockDao;
	
	private static final Mysql my = new Mysql(1);
	
	@Override
	public void lock() {
		//阻塞锁,不拿到资源不罢休
		if (!tryLock()) {
			try {
				//如果没拿到,睡一下再拿
				Thread.sleep(new Random().nextInt(10)+1);
			} catch (InterruptedException e) {
			}
			lock();//继续调用自身拿锁
		}
	}

	@Override
	public boolean tryLock() {
		//非阻塞锁,拿一次,拿到就拿到了,拿不到就撤
		try {
			mysqlLockDao.save(my);//插入成功即是拿到了
			return true;
		} catch (Exception e) {
			//有异常说明已经被其他线程拿到了,
			return false;
		}
	}

	@Override
	public void unlock() {
		//解锁,将值删除即可
		mysqlLockDao.delete(my);
	}

	@Override
	public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
		return false;
	}

	@Override
	public void lockInterruptibly() throws InterruptedException {
		
	}
	
	@Override
	public Condition newCondition() {
		return null;
	}

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值