基于Mysql实现锁机制

1 ReentrantLock

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

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

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

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

2 通过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;
    }

}

猜你喜欢

转载自blog.csdn.net/junmoxi/article/details/80876984