jetbrains tkinter ionic3 vue钩子函数 vue数据绑定 nginx学习视频 jquery的each遍历方法 bootstrap侧边栏 两个正态分布相乘 oracle一键卸载工具 coreldraw学习 配置tomcat环境变量 vue使用bootstrap idea全局替换 内存计算 车载u盘 python3网络编程 安装python教程 python输出中文 java连接sql java日期转时间戳 php实例代码 磁盘分区软件 flash实例 销售单打印软件 stata软件 隐藏虚拟键 零基础学python js延迟加载的方式 hexworkshop 编程语言实现模式 lol语音包 苹果x银色 cad自动保存位置 ipad上市时间 计划任务软件 5s降级 php验证码 无线中继是什么意思 linux添加用户
当前位置: 首页 > 学习教程  > 编程语言

漫谈锁

2021/2/13 16:19:05 文章标签: 测试文章如有侵权请发送至邮箱809451989@qq.com投诉后文章立即删除

什么是锁 假设世界上只有一个人,那么锁是不会出现的。因为锁是为了防范外人的不法行为,如果只有一个人,那就谈不上外人,那当然锁就没有必要。即使有多个人,如果这两个人井水不犯河水,也没有提防的必要。可…

什么是锁

假设世界上只有一个人,那么锁是不会出现的。因为锁是为了防范外人的不法行为,如果只有一个人,那就谈不上外人,那当然锁就没有必要。即使有多个人,如果这两个人井水不犯河水,也没有提防的必要。可是现实确实,人是一个社会性的存在,人与人之间不可避免的存在各种依赖于竞争等各种情况,所以就需要制定一定的规则对其进行协调。

同样在软件开发中的锁,也是一种在多线程下的对资源的访问进行协调的手段。

协调与同步基本是中同义替换,这就不难理解在 Java 中写多线程程序使用锁时会使用 synchronized 了。示例代码如下:

Object monitor = new Object();

void doSomething(){
      sychronized(monitor){
             //业务逻辑省略
      }
}

让我们详细考察下上述示例代码。

既然是锁是一个协调者,而我们的口头禅都是“从中协调”。由此可见,协调者是一个中间方。而在上述代码中的 monitor 就是这样一个中间方,它夹在两个(或多个)线程之间做协调工作。上述代码的工作方式有个学名叫做监视器模式(其实英文名就是 monitor),它工作的原理是,在 sychronized 代码块的入口和出口处,分别执行 monitorenter 和monitorexit 两条字节码指令,本质上,就是在执行代码之前,在 monitor里写入当前线程的 id,其它线程看到 monitor 已经有了线程,而且不是自己,就会进入等待,知道当前线程退出(正常执行完毕或者异常),等待的线程才会被唤醒,再次进入锁的竞争过程中。

让我们再来看看,锁它锁的究竟是什么。既然锁是一种多线程的协调,那就是说,锁是在对线程运行本身进行协调。至于线程本身执行的是什么逻辑线程并不关心。也就是说,锁并不直接保证程序(或者说数据)的一致性问题。这个问题由开发者自己保证。

锁保证的是,当前只有一个线程执行示例中的代码块。sychronized 包围的代码也有一个学名就 “临界区”。也就是说,统一时刻只有一个线程在执行临界区代码。一句话概括就是:锁的是一段代码,而不是共享的资源。锁保证共享自己安全的方式,就是保证临界区代码是访问共享资源的唯一路径。

锁的分类

谈了锁的作用,那么有一个问题,为什么会存在这么多的锁的种类呢?如乐观锁,悲观锁,读写锁,重入锁等。这么多锁出现的动因是什么呢?

锁是一种对并发程序协调的方式,用于保证程序的正确性(一致性)。而显然,这种协调对性能是有损的。可以想象多了一个协调者,系统就变复杂了,程序需要多出来一些协调的工作。而这么多种的锁的出现的原因,无非是在对锁带来的新的问题。其中最主要的就是性能问题。

也就是说,各种锁的出现,都是针对不同的场景,在性能与一致性上做的取舍。

乐观 VS 悲观

既然锁是一种协调,有人就想了,不加锁可不可以实现同一目的呢?这些人就是所谓的“本质思考者”。他们在想,既然锁是一种协调机制,可不可以去掉中间的协调方呢?这就是乐观锁了。乐观锁实际就是根本不加锁,在程序执行时自己对当前状态做判断,是否合适进行操作。

全局锁 vs 局部锁

全局锁有一个STW(stop the world)的时间。只要有一个线程在执行,所有线程都得等着。这就相当于,张三在睡觉的时候,全世界所有人都不能睡。其它人就怒了:我他妈找谁惹谁了?是啊,只有张三睡的不是别人的床,为什么别人不能谁。

类比到线程里,只有线程之间的逻辑没有依赖关系,完全可以一起执行嘛。也就是说,我们不能全部一棒子打死,要把大的逻辑拆分成小逻辑,没有依赖的线程完全可以并行执行。

比如在 JUC中的ConcurrentHashmap就是利用了分段锁这种局部锁,降低了锁的力度,如果两个线程不是操作同一数据元素,完全可以并发运行嘛。

数据库中也有这个概念。下面以 mysql 为例。

mysql中的锁

mysql 是插件式架构。在MyIsam中只有一种锁,那就是表锁。在Innodb中存在另外一种锁,那就是行锁,这在保证一致性的同时也保证了一定的并发性能。我想这是Innodb越来越被广泛采纳的原因之一吧。

mysql 根据在不同的查询条件下,是通过选择不同的加锁算法(记录锁,行锁,间隙锁,临键锁)来实现局部锁的。


本文链接: http://www.dtmao.cc/news_show_700002.shtml

附件下载

相关教程

    暂无相关的数据...

共有条评论 网友评论

验证码: 看不清楚?