用sql语句,有哪位大神能举个例子吗。如果能给过程,感激不尽谢谢谢谢!谢谢谢谢谢谢谢谢谢
用银行转账的列子非常好,同一个表,一个加一个减。通过事务实现。
可以, 我把我以前测试过的代码整理一下
技术springboot+mybatis-plus+mysql
这是前端时间我测试自旋锁的代码,有点乱
实体对应数据库中的表cs
package com.xm.officialaccounts.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.annotation.Version;
import lombok.Data;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
/**
* @author
* @date created in 9:26 2021/5/8
*/
@Data
@Entity
@Table(name = "cs")
@TableName("cs")
public class compareAndSwap {
@Id
@TableId(value = "id")
String id;
Integer val;
@Version
Integer version;
}
接口
package com.xm.officialaccounts.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.xm.officialaccounts.entity.compareAndSwap;
/**
* @author
* @date created in 9:55 2021/5/8
*/
public interface CsService extends IService<compareAndSwap> {
public void updateById(String id);
void selectForUpdate();
void sub(String id);
void save();
compareAndSwap sel();
}
接口实现类,操作数据库的。
@Transactional(rollbackFor = Exception.class)这个注解是开启事物,可以用在类上面(全部)也可以用在具体某个方法上面
package com.xm.officialaccounts.service;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xm.officialaccounts.entity.compareAndSwap;
import com.xm.officialaccounts.mapper.csMapper;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
/**
* @author
* @date created in 9:55 2021/5/8
*/
@Service
@Transactional(rollbackFor = Exception.class)
public class CsServiceImpl extends ServiceImpl<csMapper, compareAndSwap> implements CsService{
@Resource
csMapper csMapper;
@Override
public void updateById(String id){
String key = "cs" +id;
synchronized (key.intern()){
compareAndSwap cs = csMapper.selectById(id);
System.out.println("初始id:"+id+"的version"+ cs.getVersion());
cs.setVal(cs.getVal() + 10);
int r = csMapper.updateById(cs);
}
}
@Override
public void selectForUpdate(){
compareAndSwap cs = csMapper.selectByIdForUpdate(10);
System.out.println("初始的version"+ cs.getVersion());
int r = csMapper.update(cs.getId(),cs.getVal() + 10);
if(r < 1){
compareAndSwap cs2 = csMapper.selectByIdForUpdate(10);
System.out.println("Thread:"+Thread.currentThread().getId()+" version错误,使用的version:"+cs.getVersion()+" " +
"正确的version:"+cs2.getVersion());
}else {
cs = csMapper.selectById(10);
System.out.println("Thread:"+Thread.currentThread().getId()+" val:"+cs.getVal());
}
}
@Override
public void sub(String id) {
csMapper.sub(id);
}
@Override
public void save() {
compareAndSwap cs2 = new compareAndSwap();
baseMapper.insert(cs2);
System.out.println(cs2.getId());
}
@Override
public compareAndSwap sel() {
return baseMapper.selectById("1394927127662084100");
}
}
controller
代码用了线程池,开启多个线程。启动后,在浏览器中或者postman输入localhost:8080/cs/id,这个id是参数,你数据库中的id
package com.xm.officialaccounts.controller;
import com.xm.officialaccounts.entity.compareAndSwap;
import com.xm.officialaccounts.service.CsService;
import com.xm.officialaccounts.service.CsServiceImpl;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
/**
* @author lichao
* @date created in 9:59 2021/5/8
*/
@RestController
public class testCompareAndSwapLock{
@Resource
CsService csService;
@GetMapping("/sel")
public Object sel(){
return csService.sel();
}
@GetMapping("/cs")
public void test(@RequestParam(required = false) String id){
thr(csService,id);
}
public void thr(CsService csService,String id) {
ExecutorService pool = new ThreadPoolExecutor(50,2000,2000, TimeUnit.MILLISECONDS,
new SynchronousQueue<Runnable>(), Executors.defaultThreadFactory(),
new ThreadPoolExecutor.AbortPolicy());
for(int i=0;i<2000;i++) {
pool.execute(new ThreadTask(csService,id));
}
}
static class ThreadTask implements Runnable{
CsService csService;
String id;
public ThreadTask(CsService csService,String id) {
this.csService = csService;
this.id = id;
}
@Override
public void run(){
csService.updateById(id);
}
}
}
配置文件
server.port=8080
#数据库相关配置
spring.datasource.url=jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2b8\
&useSSL=false&autoReconnect=true
spring.datasource.username=root
spring.datasource.password=root
pom.xml依赖 maven管理
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.5</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.xm</groupId>
<artifactId>officialaccounts</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>officialaccounts</name>
<description>official accounts project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-spring-boot-starter</artifactId>
<version>2.0.2</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.38</version>
</dependency>
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>2.0.1.Final</version>
</dependency>
<dependency>
<groupId>javax.persistence</groupId>
<artifactId>javax.persistence-api</artifactId>
<version>2.2</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.6</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.0</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-core</artifactId>
<version>3.4.0</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>4.5.15</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
CsServiceImpl这个里面的updateById方法我加锁了,是线程安全的
你可以改成下面这样试试
public void updateById(String id){
// 没有加锁所以就可能读到修改前的,另外一个线程也在修改就错了
compareAndSwap cs = csMapper.selectById(id);
System.out.println("初始id:"+id+"的version"+ cs.getVersion());
cs.setVal(cs.getVal() + 10);
int r = csMapper.updateById(cs);
}
另外如果是来多个线程去执行这样的,在xml当中定义的sql,update table set val = val +10 where id = ?,经过我测试是正确的,update是会加锁的
满意的话右上角采纳
您好,我是有问必答小助手,您的问题已经有小伙伴解答了,您看下是否解决,可以追评进行沟通哦~
如果有您比较满意的答案 / 帮您提供解决思路的答案,可以点击【采纳】按钮,给回答的小伙伴一些鼓励哦~~
ps:问答VIP仅需29元,即可享受5次/月 有问必答服务,了解详情>>>https://vip.csdn.net/askvip?utm_source=1146287632