一、悲观锁
(1)mysql悲观锁
下面表需要加索引为行锁,不加索引为表锁
①.查询和修改必须在一个事务中
/**
* 更新Inter数据
*/
@Override
@Transactional
public void updateInterData() {
InterBean interBean = interMapper.queryInterData("interface1");
Long interUrl = interBean.getInterUrl();
interUrl+=1;
interBean.setInterUrl(interUrl);
interMapper.updateInterData(interBean);
}
②. 查询语句末尾需要加for update
(2)代码块实现
1、synchronized
synchronized修饰普通方法,锁对象默认为this
public class SynchronizedObjectLock implements Runnable {
static SynchronizedObjectLock instence = new SynchronizedObjectLock();
@Override
public void run() {
// 同步代码块形式——锁为this,两个线程使用的锁是一样的,线程1必须要等到线程0释放了该锁后,才能执行
synchronized (this) {
System.out.println("我是线程" + Thread.currentThread().getName());
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "结束");
}
}
public static void main(String[] args) {
Thread t1 = new Thread(instence);
Thread t2 = new Thread(instence);
t1.start();
t2.start();
}
}
2、lock锁
-
lock()
: 加锁 -
unlock()
: 解锁 -
tryLock()
: 尝试获取锁,返回一个boolean值 -
tryLock(long,TimeUtil)
: 尝试获取锁,可以设置超时
Lock一般使用的例子,注意ReentrantLock是Lock接口的实现。
package com.hjt.lock;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class LockTest {
private Lock lock = new ReentrantLock();
//需要参与同步的方法
private void method(Thread thread){
try {
lock.lock();
System.out.println("线程名"+thread.getName() + "获得了锁");
}catch(Exception e){
e.printStackTrace();
} finally {
lock.unlock();
System.out.println("线程名"+thread.getName() + "释放了锁");
}
}
public static void main(String[] args) {
LockTest lockTest = new LockTest();
//线程1
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
lockTest.method(Thread.currentThread());
}
}, "t1");
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
lockTest.method(Thread.currentThread());
}
}, "t2");
t1.start();
t2.start();
}
}
//执行情况:线程名t1获得了锁
// 线程名t1释放了锁
// 线程名t2获得了锁
// 线程名t2释放了锁
二、乐观锁
(1)CAS机制
CAS操作包括了3个操作数:
1) 需要读写的内存位置(V)
2) 进行比较的预期值(A)
3) 拟写入的新值(B)
(2)版本号机制
1、MyBatis-Plus乐观锁
数据库中添加version字段
取出记录时,获取当前version
SELECT id,`name`,price,`version` FROM product WHERE id=1
更新时,version + 1,如果where语句中的version版本不对,则更新失败
UPDATE product SET price=price+50, `version`=`version` + 1 WHERE id=1 AND`version`=1
修改实体类
@Data
public class Product {
private Long id;
private String name;
private Integer price;
@Version //标识乐观锁版本号字段
private Integer version;
}
添加乐观锁插件配置
@Configuration
//扫面指定的mapper包
@MapperScan("com.xin.mybatisplus2.mapper")
public class MyBatisPlusConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor=new MybatisPlusInterceptor();
//new PaginationInnerInterceptor(DbType.MYSQL):创建分页插件,数据库类型是MySQL
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
//添加乐观锁插件
interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
return interceptor;
}
}
服务器托管,北京服务器托管,服务器租用 http://www.fwqtg.net