从分布式锁角度理解Java的synchronized关键字
分布式锁
分布式锁就以zookeeper
为例,zookeeper
是一个分布式系统的协调器,我们将其理解为一个文件系统,可以在zookeeper
服务器中创建或删除文件夹或文件.设D为一个数据系统,不具备事务能力,在并发状态下可能出现对单个数据同时读写.客户端A,B是数据系统D提供的客户端,能够对其读写.
几个关键角色已经登场,D是一个不提供事务行为的数据系统,其存放的数据可被读写,在单客户端条件下可以保证数据的可靠,但是在两个客户端可能并发请求时就变得不可靠,A写的数据可能被B覆盖,B读的数据可能是A没有写完的数据.在不修改D源码为其提供原子性操作的前提下,我们可以考虑分布式锁.
客户端的原始API
void write(){
// 写数据
}
void read(){
// 读数据
}
如何做呢,核心就是以zookeeper
为媒介.
修改客户端API,如果读或者写,我们首先要在zookeeper
上创建一个文件夹,如果创建成功,我们就执行读写操作,如果不成功(代表已经有人创建了)我们就一直尝试创建,直到创建成功.当创建成功时,对D系统的数据进行读写操作,完成后删除zookeeper
上创建的文件夹并退出读写方法.
void write(){
while(在zookeeper上创建文件夹) {
写操作;
删除zookeeper的刚创建的文件夹;
return;
}
}
这样就完成了一个分布式并发行为的同步.假设A已经创建了文件夹,B就没办法进行后续操作,会一直尝试创建文件夹,A执行完操作之后删除文件夹,B才有机会进行在D系统上的操作.这个例子中产生了一个临界资源:D系统的数据,和一个竞态条件:A和B并发读写.(实际上zookeeper
中是可以为监听者发送文件情况的,比如我创建文件夹没有成功,可以监听该文件夹,当文件夹变化时会通知你,这时候你就可以再尝试创建文件夹了(很像wait和notify),但是为了不把重心放在zookeeper上就没有改成监听模式)
Java中Synchronized关键字
那我们再回到Java
中的synchronized
关键字上来,如果你还没理解上面的行为和synchronized
的关系你可以继续往后看.
synchronized
究竟锁住的是什么呢,锁住的是一块内存,我们在内存中的某个位置设置一个值为0,当该值为0时,一个线程为了修改临界资源将其设置为1,然后读写操作,读写结束将其设置为0,其他线程可以再次将其改为1,进行读写,结束后再将其置为0......这块内存存储在每个对象的对象头中,我们称其为锁标志位(实际上所标志位不是简单的0和1,锁标志位分为四种状态:无锁,偏向锁,轻量级锁,和重量级锁,并发中还涉及锁升级等,但本文不做细究,有兴趣的读者可以查阅相关资料).
当进入synchronized
代码块或者方法的时候,你会像上面说的分布式锁那样"创建一个文件夹",其他线程无法"创建文件夹"就会一直去尝试,当代码块或方法结束的时候会"删除文件夹",其他线程可以去抢夺创建文件夹的机会.synchronized
可以看做一道门,锁住的对象可以看做是门票.千万不要认为synchronized
锁住的是临界资源,synchronized
是以某个对象的锁标志作为入场券去约束竞态线程之间行为:我只有一张门票,我只给一个人.
看一下synchronized
的用法,多个线程之间的竞态行为一定要是用相同的门票去约束.
// 这锁住的是
class Foo{
// 这锁住的是类对象
static synchronized void bar();
// 这锁住的是this,即实例对象
synchronized void bar();
// 等价于static synchronized
void bar(){
synchronized(Foo.class){};
}
// 等价于synchronized实例方法
void bar(){
synchronized(this){}
}
}
对于静态方法需要注意一点(假如你想观察偏向锁的变化),实例方法可以直接观察实例对象的对象头上的锁标志位,但是静态方法需要观察Foo.class对象的锁标志位,如果观察实例对象的锁标志位会竹篮打水哟.
从分布式锁角度理解Java的synchronized关键字的更多相关文章
- Java对象锁和类锁全面解析(多线程synchronized关键字)
最近工作有用到一些多线程的东西,之前吧,有用到synchronized同步块,不过是别人怎么用就跟着用,并没有搞清楚锁的概念.最近也是遇到一些问题,不搞清楚锁的概念,很容易碰壁,甚至有些时候自己连用没 ...
- 【面试普通人VS高手系列】请说一下你对分布式锁的理解,以及分布式锁的实现
一个工作了7年的Java程序员,私信我关于分布式锁的问题. 一上来就两个灵魂拷问: Redis锁超时怎么办? Redis主从切换导致锁失效怎么办? 我说,别着急,这些都是小问题. 那么,关于" ...
- 从源码角度理解Java设计模式——装饰者模式
一.饰器者模式介绍 装饰者模式定义:在不改变原有对象的基础上附加功能,相比生成子类更灵活. 适用场景:动态的给一个对象添加或者撤销功能. 优点:可以不改变原有对象的情况下动态扩展功能,可以使扩展的多个 ...
- java基础Synchronized关键字之对象锁
java中Synchronized关键字之对象锁 当有多个线程对一个共享数据进行操作时,需要注意多线程的安全问题. 多线程的同步机制对资源进行加锁,使得在同一个时间,只有一个线程可以进行操作,同 ...
- Java 多线程 —— synchronized关键字
java 多线程 目录: Java 多线程——基础知识 Java 多线程 —— synchronized关键字 java 多线程——一个定时调度的例子 java 多线程——quartz 定时调度的例子 ...
- Java的synchronized关键字:同步机制总结
JAVA中synchronized关键字能够作为函数的修饰符,也可作为函数内的语句,也就是平时说的同步方法和同步语句块.搞清楚synchronized锁定的是哪个对象,就能帮助我们设计更安全的多线程程 ...
- 【原创】对Java的synchronized关键字的学习
在Java中,每一个线程都有一个内部锁.当我们使用synchronized关键字时,就是利用这个内部锁来实现线程对某个对象的锁定控制. 那么,如果某个对象中有两个方法,方法一和方法二都使用了synch ...
- Java基础-synchronized关键字的用法(转载)
synchronized--同步 顾名思义是用于同步互斥的作用的. 这里精简的记一下它的使用方法以及意义: 当synchronized修饰 this或者非静态方法或者是一个实例的时候,所同步的锁是加在 ...
- java中synchronized关键字分析
今天我们来分析一下java中synchronized关键字.首先来看一段java代码:(本地编译环境为mac,jdk1.8的环境) Demo.java package com.example.spri ...
随机推荐
- Ubuntu mysql安装与使用
Ubuntu 下安装 mysql 运行下面的shell代码 #安装mysql sudo apt-get -y install mysql-server sudo apt-get -y install ...
- python中的itertools模块简单使用
itertools 高效循环下创建循环器的标准库 Infinite itertools,无限迭代器 itertools.count(start=0, step=10) 默认返回一个从0开始,依次+10 ...
- kubernetes常见命令
kubernetes命令 kubectl get pod --all-namespaces查看pod节点 kubectl delete -n service/pods/deplay 删除指定内容 ku ...
- Python推导式详解,带你写出比较精简酷炫的代码
Python推导式详解,带你写出比较精简酷炫的代码 前言 1.推导式分类与用法 1.1 列表推导 1.2 集合推导 1.3 字典推导 1.4 元组推导?不存在的 2.推导式的性能 2.1 列表推导式与 ...
- 史上最全的Excel导入导出之easyexcel
喝水不忘挖井人,感谢阿里巴巴项目组提供了easyexcel工具类,github地址:https://github.com/alibaba/easyexcel 文章目录 环境搭建 读取excel文件 小 ...
- GoLang设计模式15 - 策略模式
策略模式是一种行为型设计模式.通过策略模式,可以在运行时修改一个对象的行为. 接下来仍然是通过例子来了解策略模式.比如说内存缓存,这是我们在开发中经常使用的东西,大家应该都有一定的了解,接下来就用内存 ...
- UE4中C++编程(一)
一: C++工程和Gameplay框架 GameInstance 它适合放置独立于关卡的信息,比如说显示UI. GameMode 表示游戏玩法, 包含游戏进行的规则和胜利条件等等信息,游戏模式是和关卡 ...
- Django笔记&教程 总目录
本篇博客只有目录,正文内容在目录章节链接的博客里 除目录本身外,没有链接的章节,说明内容还没开始编辑 本项目笔记仍在不断创作中,还有些内容会根据自身所学不断更新完善 本项目主要为markdwon文档, ...
- C/C++ QT QChart 绘制组件应用
QtCharts 组件是QT中提供图表绘制的模块,该模块可以方便的绘制常规图形,Qtcharts 组件基于GraphicsView模式实现,其核心是QChartView和QChart的二次封装版. 在 ...
- pg_probackup
[1] https://postgrespro.com/docs/enterprise/13/app-pgprobackup PITR依赖continuous WAL archiving: Makin ...