functioncocktailSort(array) { let left,right,index,i left = 0// 数组的起始索引 right = array.length - 1// 数组索引的最大值 index = left // 临时变量
// 判断数组中是否有多个元素 while (left < right) { let isSorted = false // 每一次进入while循环,都会找出相应范围内最大最小的元素并分别放到相应的位置 // 大的排到后面 for (let i = left; i < right; i++) { // 从左到右扫描,找出较大的元素 if (array[i] > array[i + 1]) { swap(array, i, i + 1) index = i // 记录当前索引 isSorted = true } } right = index // 记录最后一个交换的位置 // 小的排到前面 for (let i = right; i > left; i--) { if (array[i] < array[i - 1]) { // 从右到左扫描,找出较小的元素 swap(array, i, i - 1) index = i isSorted = true } } left = index // 记录最后一个交换的位置 if (!isSorted) { // 没有需要排序的元素了,退出循环 break } } return arr }
// 鸡尾酒排序 funccocktailSort(arr []int) []int { var i int left, right := 0, len(arr)-1 index := left // 临时变量 // 判断数组中是否有多个元素 for left < right { isSort := false// 标志位,如果内循环没有发生交换元素,退出循环 for i = left; i < right; i++ { // 从左往右扫描,找出较大的元素 if arr[i] > arr[i+1] { arr[i], arr[i+1] = arr[i+1], arr[i] isSort = true index = i } } right = index for i = right; i > left; i++ { // 从右向左扫描,找出较小的元素 if arr[i] < arr[i-1] { arr[i], arr[i-1] = arr[i-1], arr[i] isSort = true index = i } } left = index if !isSort { break } } return arr }
可以想办法加入一个不会重复修改的值数据来作为版本号,即 version 参数,version 只能增加,不能减少。乐观锁在每次执行数据修改时,都需要去比对 version,如果一致,则更新数据的同时,也要更新 version。
1 2 3 4 5 6 7 8
-- 给 worker 表添加 version 列 ALTERTABLE `worker` ADDCOLUMN `version` BIGINT(20) NOTNULLDEFAULT'0' COMMENT '乐观锁版本号'; -- 读取数据,记录 version 的值 SELECT*FROM worker WHERE id =1; -- 比对 version 是否符合预期,更新数据和 version UPDATE worker SET salary =2000, version = version +1WHERE id =1AND version =0; -- 再次读取数据,校验是否符合预期 SELECT*FROM worker WHERE id =1;
乐观锁同样可以使用时间戳来实现,一样的道理.
go伪代码事例
1 2 3 4 5 6 7 8 9 10 11
for { // 强制更新 Stock、Version字段,并时Version + 1 result := tx.Model(&model.Inventory{}).Select("Stocks", "Version").Where("goods = ? and version = ?", goodInfo.GoodsId, inv.Version).Updates(model.Inventory{Stocks: inv.Stocks, Version: inv.Version + 1}) if result.RowAffected == 0 { // 更新失败重试 log.Printf()("更新失败") } else { // 退出循环 break } }