乐观锁、悲观锁、要实践

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 transaction mysql> 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 transaction mysql> 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 transaction 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 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: 0 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;
+----+--------+-----------+---------+
| 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] 乐观悲观锁,自旋互斥锁等等的更多相关文章

  1. Java 中15种锁的介绍:公平锁,可重入锁,独享锁,互斥锁,乐观锁,分段锁,自旋锁等等

    Java 中15种锁的介绍 Java 中15种锁的介绍:公平锁,可重入锁,独享锁,互斥锁,乐观锁,分段锁,自旋锁等等,在读很多并发文章中,会提及各种各样锁如公平锁,乐观锁等等,这篇文章介绍各种锁的分类 ...

  2. C# lock 语法糖实现原理--《.NET Core 底层入门》之自旋锁,互斥锁,混合锁,读写锁

    在多线程环境中,多个线程可能会同时访问同一个资源,为了避免访问发生冲突,可以根据访问的复杂程度采取不同的措施 原子操作适用于简单的单个操作,无锁算法适用于相对简单的一连串操作,而线程锁适用于复杂的一连 ...

  3. C# lock的语法糖原理--《.net core 底层入门》之自旋锁,互斥锁,混合锁,读写锁

    在多线程环境中,多个线程可能会同时访问同一个资源,为了避免访问发生冲突,可以根据访问的复杂程度采取不同的措施 原子操作适用于简单的单个操作,无锁算法适用于相对简单的一连串操作,而线程锁适用于复杂的一连 ...

  4. Java 种15种锁的介绍:公平锁,可重入锁,独享锁,互斥锁等等…

    Java 中15种锁的介绍 1,在读很多并发文章中,会提及各种各样的锁,如公平锁,乐观锁,下面是对各种锁的总结归纳: 公平锁/非公平锁 可重入锁/不可重入锁 独享锁/共享锁 互斥锁/读写锁 乐观锁/悲 ...

  5. 【python】-- GIL锁、线程锁(互斥锁)、递归锁(RLock)

    GIL锁 计算机有4核,代表着同一时间,可以干4个任务.如果单核cpu的话,我启动10个线程,我看上去也是并发的,因为是执行了上下文的切换,让看上去是并发的.但是单核永远肯定时串行的,它肯定是串行的, ...

  6. 举例讲解Python中的死锁、可重入锁和互斥锁

    举例讲解Python中的死锁.可重入锁和互斥锁 一.死锁 简单来说,死锁是一个资源被多次调用,而多次调用方都未能释放该资源就会造成死锁,这里结合例子说明下两种常见的死锁情况. 1.迭代死锁 该情况是一 ...

  7. Java中的锁-悲观锁、乐观锁,公平锁、非公平锁,互斥锁、读写锁

    总览图 如果文中内容有错误,欢迎指出,谢谢. 悲观锁.乐观锁 悲观锁.乐观锁使用场景是针对数据库操作来说的,是一种锁机制. 悲观锁(Pessimistic Lock):顾名思义,就是很悲观,每次去拿数 ...

  8. linux自旋锁、互斥锁、信号量

    为了避免并发,防止竞争.内核提供了一组同步方法来提供对共享数据的保护. 我们的重点不是介绍这些方法的详细用法,而是强调为什么使用这些方法和它们之间的差别. Linux 使用的同步机制可以说从2.0到2 ...

  9. GIL全局解释器锁+GIL全局解释器锁vs互斥锁+定时器+线程queue+进程池与线程池(同步与异步)

    以多线程为例写个互斥锁 from threading import Thread ,Lockimport timemutex = Lock() n = 100 def task(): global n ...

随机推荐

  1. 分割视图控制器(UISplitViewController)

    这种控制器只能用于iPad,它可以在iPad屏幕中显示两个不同的场景:在横向模式下,左边显示一个表,供用户选择:用户选择表中的元素后,详细视图将显示该元素的详细信息.如果iPad被旋转到纵向模式,表将 ...

  2. Redis学习篇(八)之连接相关

    PING 测试客户端和服务器之间的连接是否有效,有效返回PONG ECHO 打印特定的信息, 如: ECHO 'HELLO WORLD' QUIT/EXIT 断开当前客户端与服务器之间的连接,可以重连 ...

  3. HDU 5692 Snacks

    题目链接[http://acm.hdu.edu.cn/showproblem.php?pid=5692] 题意:一棵树,每个节点有权值,有两种操作:1.修改某个点的权值,2.求以x根的子树中的节点到根 ...

  4. SQL Server附加数据库提示“版本为661,无法打开,支持655版本……”

    在我们使用别人导出的数据库的时候,有时候我们会通过附加数据库的方法,把别人导出的数据库附加到我们的电脑中,这时,或许你会遇到这种问题,附加时,提示版本为XXX,无法打开,支持AAA版本. 这是怎么回事 ...

  5. dalvik 基于 jvm 的改进

    韩梦飞沙  韩亚飞  313134555@qq.com  yue31313  han_meng_fei_sha 几个class 变成一个dex.constant pool 省内存 zygote ,co ...

  6. UI/GUI/UE/UX/ID/UED/UCD的区别

    简述: UI (User Interface):用户界面 UE (User Experience):用户体验 ID (Interaction design):交互设计 UID (User Interf ...

  7. JxBrowser概述与简单应用

    Q:JxBrowser是什么? JxBrowser是一个跨平台的Java库,允许将基于Google Chromium的Web浏览器组件集成到Java Swing / AWT / JavaFX应用程序中 ...

  8. Linux下对拍程序

    在程序对应文件夹下存为.sh文件 在终端命令中进入相应文件夹,用 sh XXX.sh 调用 while true; do ./datamaker>tmp.in ./baoli<tmp.in ...

  9. 《深入理解Spark-核心思想与源码分析》(六)第六章计算引擎

    RDD是Spark对各类数据计算模型的统一抽象,被用于迭代计算过程以及任务输出结果的缓存读写. 在所有MapReduce框架中,shuffle是连接map任务和reduce任务的桥梁.shuffle性 ...

  10. linux常见命令集合(下)

    1. tar zcvf backup-$(date "+%Y-%m-%d").tar.gz demo01dir 常用命令集合 echo helloworld date “+%y-% ...