[Todo] 乐观悲观锁,自旋互斥锁等等
乐观锁、悲观锁、要实践
http://chenzhou123520.iteye.com/blog/1860954 《mysql悲观锁总结和实践》
http://chenzhou123520.iteye.com/blog/1863407 《mysql乐观锁总结和实践》
http://outofmemory.cn/sql/optimistic-lock-and-pessimistic-lock
注意,以下的表里面的列名,一定要用 `` 反引号来包括。
mysql> create table `t_goods` ( -> `id` bigint(11) NOT NULL AUTO_INCREMENT, -> `status` bigint(11) DEFAULT 0, -> `name` varchar(32) DEFAULT NULL, -> `version` bigint(11) DEFAULT 1, -> PRIMARY KEY (`id`) -> ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; Query OK, 0 rows affected (0.13 sec)
mysql> insert into t_goods (`name`) values ('weapon'); Query OK, 1 row affected (0.07 sec)mysql> insert into t_goods (`name`) values ('equipment'); Query OK, 1 row affected (0.10 sec)
mysql> select * from t_goods;
+----+--------+-----------+---------+
| id | status | name | version |
+----+--------+-----------+---------+
| 1 | 0 | weapon | 1 |
| 2 | 0 | equipment | 1 |
+----+--------+-----------+---------+
2 rows in set (0.00 sec)
实验1,select for update 指定主键,只锁行:
首先要关闭autocommit:
mysql> set autocommit=0; Query OK, 0 rows affected (0.00 sec)mysql> show variables like 'autocommit'; +---------------+-------+ | Variable_name | Value | +---------------+-------+ | autocommit | OFF | +---------------+-------+ 1 row in set (0.00 sec)
如果不关闭,经过实验,的确不会相互影响。
关闭autocommit之后,普通的sql不放在事务里面也可以。
console A:mysql> select * from t_goods where id = 1 for update; +----+--------+--------+---------+ | id | status | name | version | +----+--------+--------+---------+ | 1 | 0 | weapon | 1 | +----+--------+--------+---------+ 1 row in set (0.00 sec)console B: mysql> select * from t_goods where id = 1; +----+--------+--------+---------+ | id | status | name | version | +----+--------+--------+---------+ | 1 | 0 | weapon | 1 | +----+--------+--------+---------+ 1 row in set (0.00 sec)mysql> select * from t_goods where id = 2 for update; +----+--------+-----------+---------+ | id | status | name | version | +----+--------+-----------+---------+ | 2 | 0 | equipment | 1 | +----+--------+-----------+---------+ 1 row in set (0.00 sec)mysql> select * from t_goods where id = 1 for update; ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
可以看出,不加for update不影响,加了for update不是同一行,不影响(仅对于主键查询有关)。
实验2,select for update 指定非主键,锁全部:
Console A: mysql> select * from t_goods where name = 'weapon' for update; +----+--------+--------+---------+ | id | status | name | version | +----+--------+--------+---------+ | 1 | 0 | weapon | 1 | +----+--------+--------+---------+ 1 row in set (0.00 sec)Console B: mysql> select * from t_goods; +----+--------+-----------+---------+ | id | status | name | version | +----+--------+-----------+---------+ | 1 | 0 | weapon | 1 | | 2 | 0 | equipment | 1 | +----+--------+-----------+---------+ 2 rows in set (0.00 sec)mysql> select * from t_goods where name = 'equipment' for update; ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transactionmysql> select * from t_goods where id = 2 for update; ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
实验3,查询主键没查到,不锁:
Console A: mysql> select * from t_goods where id=3 for update; Empty set (0.01 sec)Console B: mysql> select * from t_goods for update; +----+--------+-----------+---------+ | id | status | name | version | +----+--------+-----------+---------+ | 1 | 0 | weapon | 1 | | 2 | 0 | equipment | 1 | +----+--------+-----------+---------+ 2 rows in set (0.00 sec)
说明,主键没查到数据,不加锁。
实验4,查询非主键,没查到,锁全部,table lock.
Console A: mysql> select * from t_goods where name = 'abc' for update; Empty set (0.00 sec)Console B: mysql> select * from t_goods for update; ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transactionmysql> select * from t_goods where id = 1 for update; ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
实验5:查询主键不明确,为范围,大于小于,只锁相关的行;
Console A: mysql> select * from t_goods where id > 1 for update; +----+--------+-----------+---------+ | id | status | name | version | +----+--------+-----------+---------+ | 2 | 0 | equipment | 1 | +----+--------+-----------+---------+ 1 row in set (0.00 sec)Console B: mysql> select * from t_goods where id = 1 for update; +----+--------+--------+---------+ | id | status | name | version | +----+--------+--------+---------+ | 1 | 0 | weapon | 1 | +----+--------+--------+---------+ 1 row in set (0.00 sec)mysql> select * from t_goods where id = 2 for update; ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
实验5:查询主键不明确,!=或者<>,锁全部;
Console A: mysql> select * from t_goods where id != 1 for update; +----+--------+-----------+---------+ | id | status | name | version | +----+--------+-----------+---------+ | 2 | 0 | equipment | 1 | +----+--------+-----------+---------+ 1 row in set (0.00 sec)Console B: mysql> select * from t_goods where id = 1 for update; ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transactionConsole A: mysql> select * from t_goods where id <> 1 for update; +----+--------+-----------+---------+ | id | status | name | version | +----+--------+-----------+---------+ | 2 | 0 | equipment | 1 | +----+--------+-----------+---------+ 1 row in set (0.00 sec)Console B: mysql> select * from t_goods where id = 1 for update; ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
实验6,对于普通索引,也类似于主键的效果:
未加索引之前,锁全表: console A: mysql> select * from t_goods where status = 1 for update; +----+--------+--------+---------+ | id | status | name | version | +----+--------+--------+---------+ | 1 | 1 | weapon | 1 | +----+--------+--------+---------+ 1 row in set (0.00 sec)console B: mysql> select * from t_goods where id = 2 for update; ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction加了索引之后,只锁行: console A: mysql> alter table t_goods add index index_name(`status`); Query OK, 0 rows affected (0.15 sec) Records: 0 Duplicates: 0 Warnings: 0mysql> select * from t_goods where status = 1 for update; +----+--------+--------+---------+ | id | status | name | version | +----+--------+--------+---------+ | 1 | 1 | weapon | 1 | +----+--------+--------+---------+ 1 row in set (0.00 sec)console B: mysql> select * from t_goods where id = 2 for update; +----+--------+-----------+---------+ | id | status | name | version | +----+--------+-----------+---------+ | 2 | 0 | equipment | 1 | +----+--------+-----------+---------+ 1 row in set (0.00 sec)mysql> select * from t_goods where id = 1 for update; ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
乐观锁:
从业务层面加锁,一般是加上version字段,然后sql以如下形式处理:
update t_goods set status=2,version=version+1 where id=#{id} and version=#{version};
自旋锁与互斥锁
http://blog.csdn.net/a675311/article/details/49096435
自旋锁就是不听的忙检测,拿不到锁就返回。
pthread中提供的锁有:pthread_mutex_t, pthread_spinlock_t, pthread_rwlock_t。pthread_mutex_t是互斥锁,同一瞬间只能有一个线程能够获取锁,其他线程在等待获取锁的时候会进入休眠状态。因此pthread_mutex_t消耗的CPU资源很小,但是性能不高,因为会引起线程切换。 pthread_spinlock_t是自旋锁,同一瞬间也只能有一个线程能够获取锁,不同的是,其他线程在等待获取锁的过程中并不进入睡眠状态,而是在CPU上进入“自旋”等待。自旋锁的性能很高,但是只适合对很小的代码段加锁(或短期持有的锁),自旋锁对CPU的占用相对较高。 pthread_rwlock_t是读写锁,同时可以有多个线程获得读锁,同时只允许有一个线程获得写锁。其他线程在等待锁的时候同样会进入睡眠。读写锁在互斥锁的基础上,允许多个线程“读”,在某些场景下能提高性能。 诸如pthread中的pthread_cond_t, pthread_barrier_t, semaphone等,更像是一种同步原语,不属于单纯的锁。
http://www.cnblogs.com/hdflzh/p/3716156.html
http://blog.csdn.net/pi9nc/article/details/39177343
Java锁相关
http://blog.csdn.net/Evankaka/article/details/44153709 (这一篇要重点看,讲了Thread Runnable等)
http://blog.csdn.net/Evankaka/article/details/51866242(Java锁技术内幕上)
http://blog.csdn.net/evankaka/article/details/51932044(Java锁技术内幕中)
[Todo] 乐观悲观锁,自旋互斥锁等等相关推荐
- 并发编程中常见的锁机制:乐观锁、悲观锁、CAS、自旋锁、互斥锁、读写锁
文章目录 乐观锁 VS 悲观锁 悲观锁 乐观锁 CAS CAS机制 ABA问题 CAS的优缺点 互斥锁 VS 自旋锁 互斥锁 自旋锁 对比及应用场景 读写锁 实现方式 读写锁 VS 互斥锁 乐观锁 V ...
- 各类锁(互斥锁,自旋锁,读写锁,乐观锁,悲观锁,死锁)
互斥锁 当有一个线程要访问共享资源(临界资源)之前,会对线程访问的这段代码(临界区)进行加锁.如果在加锁之后没释放锁之前其他线程要对临界资源进行访问,则这些线程会被阻塞睡眠,直到解锁,如果解锁时有一个 ...
- 关抢占 自旋锁_互斥锁、自旋锁、读写锁、悲观锁、乐观锁的应用场景
前言 生活中用到的锁,用途都比较简单粗暴,上锁基本是为了防止外人进来.电动车被偷等等. 但生活中也不是没有 BUG 的,比如加锁的电动车在「广西 - 窃·格瓦拉」面前,锁就是形同虚设,只要他愿意,他就 ...
- 分布式锁:互斥锁、自旋锁、读写锁、悲观锁、乐观锁
前言 如何用好锁,也是程序员的基本素养之一了. 高并发的场景下,如果选对了合适的锁,则会大大提高系统的性能,否则性能会降低. 所以,知道各种锁的开销,以及应用场景是很有必要的. 接下来,就谈一谈常见的 ...
- 悲观|乐观锁、自旋|互斥锁、公平|非公平锁
解析锁--悲观|乐观锁.自旋|互斥锁.公平|非公平锁 悲观锁 总认为最坏的情况可能会出现,即认为数据很可能会被他人修改,因此在持有数据时总是先把资源或数据锁住.这样其他线程要请求这个资源时就会阻塞,直 ...
- Java中的锁机制 -- 乐观锁、悲观锁、自旋锁、可重入锁、读写锁、公平锁、非公平锁、共享锁、独占锁、重量级锁、轻量级锁、偏向锁、分段锁、互斥锁、同步锁、死锁、锁粗化、锁消除
文章目录 1. Java中的锁机制 1.1 乐观锁 1.2 悲观锁 1.3 自旋锁 1.4 可重入锁(递归锁) 1.5 读写锁 1.6 公平锁 1.7 非公平锁 1.8 共享锁 1.9 独占锁 1.1 ...
- Java 中15种锁的介绍:公平锁,可重入锁,独享锁,互斥锁,乐观锁,分段锁,自旋锁等等...
http://blog.51cto.com/13919357/2339446 Java 中15种锁的介绍 在读很多并发文章中,会提及各种各样锁如公平锁,乐观锁等等,这篇文章介绍各种锁的分类.介绍的内容 ...
- Java 中15种锁的介绍:公平锁,可重入锁,独享锁,互斥锁,乐观锁,分段锁,自旋锁等等
Java 中15种锁的介绍 在读很多并发文章中,会提及各种各样锁如公平锁,乐观锁等等,这篇文章介绍各种锁的分类.介绍的内容如下: 公平锁 / 非公平锁 可重入锁 / 不可重入锁 独享锁 / 共享锁 互 ...
- 嵌入式 自旋锁、互斥锁、读写锁、递归锁
互斥锁(mutexlock): 最常使用于线程同步的锁:标记用来保证在任一时刻,只能有一个线程访问该对象,同一线程多次加锁操作会造成死锁:临界区和互斥量都可用来实现此锁,通常情况下锁操作失败会将该线程 ...
最新文章
- iOS功能-统计平均下班时间
- java 获取文件权限_Java中的文件权限,检查权限和更改权限 - Break易站
- java nio.Buffer的属性变化
- 虚拟化Java应用程序:最佳实践(JavaOne 2011)
- Linux系统:centos7下搭建Nginx和FastDFS文件管理中间件
- mongo 多条件筛选_excel成本统计:如何进行区域筛选,多条件求和?
- java 事务管理 子父线程_Java中的父线程与子线程
- mysql的root用户无法给普通用户授权问题处理
- Android WindowManager简析
- c标准语言库里的i o函数,C语言文件I/O和标准I/O函数
- Android应用开发以及设计思想深度剖析(3)
- POJ 3415 Common Substrings (后缀数组,长度不小于k的公共子串的个数)
- Unity使用UniWebview插件内嵌H5游戏
- 计算机学科融合信息技术,信息技术与学科教学融合课例解析
- led拼接屏报价_液晶拼接屏报价大概多少钱一套?
- Android11 使用NTP同步时间
- 【拼多多】六一儿童节
- 聊聊新股市盈率的那些事
- C语言实现稳定的快排
- Android仿Qzone底部导航栏加号弹出菜单
热门文章
- 为什么同事写的代码那么优雅~
- mysql 相关子查询使用【主表得数据需要扩展(统计数据依赖与其他表,但是与主表有关联)】...
- DVbbs8.2入侵思路与总结
- Internet概念与TCP/ IP分层模型
- 对测试人员或开发人员来说相互沟通有多重要?
- Linux 学习_在Linux下面安装tomcat
- DirectSound 混音的实现
- 请先设置tkk_理光MP2014扫描至文件夹的设置方法
- ubuntu linux下建立stm32开发环境: 程序烧录 openocd+openjtag
- 对eventloop的研究