Redis的线程模型和事务( 五 )


因为接口1的事务是延迟3秒提交的 , 因此执行顺序是:
接口1 watch 键A ->接口1 multi开始事务 -> 接口2 修改键A -> 接口1 提交事务
结果也符合我们预想的 , 因为在接口1 watch的键值 , 被接口2修改了 , 所以接口1 的事务执行失败了 , 最终输出的日志是:
2020-10-11 23:32:14.133Thread2执行结果:key_a:change_akey_b:null2020-10-11 23:32:16.692Thread1执行结果:key_a:change_akey_b:null【Redis的线程模型和事务】@RunWith(SpringRunner.class)@SpringBootTest@AutoConfigureMockMvcpublic class DemoControllerTest {private final Logger logger = LoggerFactory.getLogger(DemoControllerTest.class);@Autowiredprivate MockMvc mockMvc;@Autowiredprivate StringRedisTemplate stringRedisTemplate;@Testpublic void transactionTest() throws InterruptedException{/*** 清空数据 , 删除 A、B 键*/stringRedisTemplate.delete(DemoController.STR_KEY_A);stringRedisTemplate.delete(DemoController.STR_KEY_B);/*** 线程1:watch A 键* 事务:修改A、B 键值 , 阻塞10秒后exec、unwatch* 输出:A、B键值*/Thread thread1 = new Thread(() -> {try {mockMvc.perform(MockMvcRequestBuilders.get("/watch"));logger.info(new StringBuffer(Thread.currentThread().getName()).append("执行结果:\n").append(DemoController.STR_KEY_A).append(":").append(stringRedisTemplate.opsForValue().get(DemoController.STR_KEY_A)).append("\n").append(DemoController.STR_KEY_B).append(":").append(stringRedisTemplate.opsForValue().get(DemoController.STR_KEY_B)).toString());} catch (Exception e) {logger.error("/watch",e);}});thread1.setName("Thread1");/*** 线程2:修改 A 键* 事务:无事务 , 无阻塞* 输出:A、B 键值*/Thread thread2 = new Thread(() -> {try {mockMvc.perform(MockMvcRequestBuilders.get("/change"));logger.info(new StringBuffer(Thread.currentThread().getName()).append("执行结果:\n").append(DemoController.STR_KEY_A).append(":").append(stringRedisTemplate.opsForValue().get(DemoController.STR_KEY_A)).append("\n").append(DemoController.STR_KEY_B).append(":").append(stringRedisTemplate.opsForValue().get(DemoController.STR_KEY_B)).toString());} catch (Exception e) {logger.error("/change",e);}});thread2.setName("Thread2");/*** 线程1 比 线程2 先执行*/thread1.start();Thread.sleep(500);thread2.start();/*** 主线程 , 等待 线程1、线程2 执行完成*/thread1.join();thread2.join();}}


推荐阅读