java 独占锁_锁分类(独占锁、分拆锁、分离锁、分布式锁)

一、java内存模型

提到同步、锁,就必须提到Java的内存模型,为了提高程序的执行效率,java也吸收了传统应用程序的多级缓存体系。

abf2be482ce772c799c9f7d85fa7c13a.png

在共享内存的多处理器体系架构中,每个处理器都拥有自己的缓存,并且定期地与主内存进行协调。在不同的处理器架构中提供了不同级别的缓存一致性(Cache Coherence),其中一部分只提供最小的保证,即允许不同的处理器在任意时刻从同一个存储位置上看到不同的值。操作系统、编译器以及运行时(有时甚至包括应用程序)需要弥合这种在硬件能力与线程安全之间的差异。

要想确保每个处理器都能在任意时刻知道其他处理器正在进行的工作,将需要非常大的开销。在大多数时间里,这种信息是不必要的。因此处理器会适当放宽存储一致性保证,以换取性能的提升。在架构定义的内存模型中将告诉应用程序可以从内存系统中获得怎样的保证,此外还定义了一些特殊的指令(称为内存栅栏),当需要共享数据时,这些指令就能实现额外的存储协调保证。为了使java开发人员无须关心不同架构内存模型之间的差异,Java还提供了自己的内存模型,并且JVM通过在适当的位置上插入内存栅栏来屏蔽在JVM与底层之平台内存模型之间的差异。

经过上面的讲解和上图,我们知道线程在运行时候有一块内存专用区域,Java程序会将变量同步到线程所在的内存。这时候会操作工作内存中的变量,而线程中的变量何时同步回到内存是不可预期的。但是java内存模型规定,通过关键词”synchronized“、”volatile“可以让java保证某些约束。

“volatile” - 保证读写的都是主内存变量。

“synchronized” - 保证在块开始时,都同步主内存值到工作内存,而快结束时,将工作内存同步会主内存。

重排序

public classPossibleReordering {static int x = 0,y=0;static int a=0,b=0;public static void main(String[] args) throwsInterruptedException {

Thread one= new Thread(newRunnable() {

@Overridepublic voidrun() {

a= 1;

x=b;

}

});

Thread two= new Thread(newRunnable() {

@Overridepublic voidrun() {

b= 2;

y=a;

}

});

one.start();two.start();

one.join();two.join();

System.out.println("x:" + x+",y:"+y);

}

}

重排序。如上图,执行结果,一般人可能认为是1,1;真正的执行结果可能每次都不一样。拜JMM重排序所赐,JMM使得不同线程的操作顺序是不同的,从而导致在缺乏同步的情况下,要推断操作的执行结果将变得更加复杂。各种使操作延迟或看似乱序执行的不同原因,都可以归为重排序。内存级的重排序会使程序的行为变得不可预测。如果没有同步,要推断出程序的执行顺序是非常困难的,而要确保在程序中正确的使用同步却是非常容易的。同步将限制编译器和硬件运行时对内存操作重排序的方式。

锁synchronized

锁实现了对临界资源的互斥访问,被synchronized修饰的代码只有一条线程可以通过,是严格的排它锁、互斥锁。没有获得对应锁对象监视器(monitor)的线程会进入等待队列,任何线程必须获得monitor的所有权才可以进入同步块,退出同步快或者遇到异常都要释放所有权,JVM规范通过两个内存屏障(memory barrier)命令来实现排它逻辑。内存屏障可以理解成顺序执行的一组CPU指令,完全无视指令重排序。

什么是锁

public class TestStatic {

public syncronized static void write(boolean flag) {

xxxxx

}

public synchronized static void read() {

xxxxx

}

}

线程1访问TestStatic.write()方法时,线程2能访问TestStatic.read()方法吗

线程1访问new TestStatic().write()方法时,线程2能访问new TestStatic().read()方法吗

线程1访问TestStatic.write()方法时,线程2能访问new TestStatic().read()方法吗

public class Test {

public syncronized void write(boolean flag) {

xxxxx

}

public synchronized void read() {

xxxxx

}

}

Test test = new Test();线程1访问test.write() 方法,线程2能否访问test.read()方法

Test a = new Test(); Test b = new Test();线程1访问a.write()访问,线程2能否访问b.read()方法

答案,java中每个对象都可以作为一个锁,而对象就决定了锁的粒度大小。

对于实例同步方法,锁是当前对象。

对于静态方法,锁是TestSTatic.class对象

对于同步代码块,锁是Synchronized括号里面配置的对象

TestStatic类,1问,作用范围全体class对象,线程1拿到,线程2就不能拿到

2问,3问同上

Test类,1问,不能,锁都是实例对象test,线程1拿到锁之后,线程2无法访问

2问,可以,线程1锁是实例a,线程2是实例b。

独占锁

如果你不敢确定该用什么锁,就用这个吧,在保证正确的前提下,后续在提高开发效率。

public class ServerStatus {

public final Set users;

public final Set quers;

public synchronized void addUser(String u ) {

users.add(u);

}

public synchronized void addQuery(String q ) {

quers.add(q);

}

public synchronized void removeUser(String u) {

users.remove(u);

}

public synchronized void removeQuery(String q) {

quers.remove(q);

}

}

分拆锁

如果在整个应用程序只有一个锁,而不是为每个对象分配一个独立的锁,那么所有同步代码块的执行就会变成串行化执行。由于很多线程都会竞争同一个全局锁,因此两个线程同时请求这个锁的概率将会剧增,从而导致更严重的竞争。所以如果将这些锁请求分到更多的锁上,就能有效降低锁竞争程度。由于等待而被阻塞的线程将更少,从而可伸缩性将提高。

上文中users、quers是两个相互独立的变量,可以将此分解为两个独立的锁,每个锁只保护一个变量,降低每个锁被请求的频率。

public class ServerStatus {

public final Set users;

public final Set quers;

public void addUser(String u ) {

synchronized(users) {

users.add(u);

}

}

public void addQuery(String q ) {

synchronized(quers) {

quers.add(q);

}

}

public void removeUser(String u) {

synchronized(users) {

users.remove(u);

}

}

public void removeQuery(String q) {

synchronized(quers) {

quers.remove(q);

}

}

}

分离锁

在某些情况下,可以将锁分解技术进一步扩展为对一组独立对象上的锁进行分解,这种情况称为锁分段。例如ConcurrencyHashMap是有一个包含16个锁的数组实现,每个锁保护所有散列桶的1/16,其中第N个散列桶由第(N mod 16)个锁来保护。假设所有关键字都时间均与分布,那么相当于把锁的请求减少到原来的1/16,可以支持多达16个的并发写入。

锁分段的劣势在于:与采用单个锁来实现独占访问相比,要获取多个锁来实现独占访问将更加困难并且开销更高,比如计算size、重hash。

bf777677df7848512eaa74dd119a8a1f.png

分布式锁

zookeeper,判断临时节点是否存在,存在就说明已经有人争抢到锁;不存在就创建节点,表明拥有该锁。

记下,以后详细研究

《分布式锁实现:数据库、redis、zookeeper》

volatile

volatile是比synchronized更轻量级的同步原语,volatile可以修饰实例变量、静态变量、以及数组变量(网上大牛说,维护的是引用,但是里面的对象。。。嘿嘿嘿)。被volatile修饰的变量,JVM规范规定,一个线程在修改完,另外的线程能读取最新的值。

但仅仅保证可见性,不保证原子性,所以volatile通常用来修饰boolean类型或者状态比较少的数据类型,而且不能用来更新依赖变量之前值的操作(例volatile++)。

volatile内部仅仅是对变量的操作多了一条cpu指令(lock#指令),它会强制写数据到缓存,如果缓存数据同时也在主存,会强制写数据更新到主存,并且使所有持有该主存数据地址的缓存统统失效,触发其他持有缓存数据的线程从主存获取最新数据,从而实现同步。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/266544.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

WinCE切换GPRS

// GPRSwitch.cpp : 定义应用程序的入口点。 //#include "stdafx.h" #include "GPRSwitch.h" #include <windows.h> #include <commctrl.h> #include "GprsXmlConfig.h" #include <connmgr.h> #include <ras.h> #includ…

url模糊匹配优化_企业必备的网站SEO优化解决方案

一、网站优化与调整倡议一个好网站不只要满足阅读者&#xff0c;还要契合搜索引擎规则、满足搜索引擎快照抓取、赋予评级、提升关键词排序等。我们站在用户角度和搜索引擎规则根底上为您提供一套完好的SEO处理计划SEO处理计划SEO倡议大纲&#xff1a;1、目的客户剖析与定位&…

项目实战 编辑

编辑本目录 01 博客系统功能需求 编辑 02 设计表结构 编辑 03 登录认证 编辑 04 用户注册 编辑 05 首页设计 编辑 06 文章详情页设计 编辑 07 后台管理页面 编辑转载于:https://www.cnblogs.com/yaya625202/p/9354610.html

全国计算机等级考试题库二级C操作题100套(第17套)

第17套&#xff1a; 程序通过定义学生结构体数组&#xff0c;存储了若干名学生的学号、姓名和3门课的成绩。函数fun的功能是将存放学生数据的结构体数组&#xff0c;按照姓名的字典&#xff08;从小到大&#xff09;排序。 请在程序的下划线处填入正确的内容并把下划线删除, …

中文能用rsa加密吗_外文文献数据库能用中文词进行检索吗?

大家使用外文文献数据库进行检索的时候可能想过一个问题&#xff1a;我们可以使用中文关键词进行检索吗&#xff1f;上文献检索课的老师可能会这样回答&#xff1a;在一般情况下&#xff0c;是不可以的。那么实际情况是怎样的呢&#xff1f;我们找几个外文文献数据库来验证一下…

长链接转短链接java_长链接生成短链接Java源码(调用百度接口)

public static DefaultHttpClient httpclient;static {httpclient new DefaultHttpClient();//httpclient (DefaultHttpClient) HttpClientConnectionManager.getSSLInstance(httpclient); // 接受任何证书的浏览器客户端}/*** 生成短连接信息** author: zhaojinhui* date: 2…

python学习[第十三篇] 条件和循环

python学习[第十三篇] 条件和循环 if语句 单一if 语句 if语句有三个部分构成&#xff0c;关键字if本身&#xff0c;判断结果真假的条件表达式&#xff0c;以及表达式为真或非0是执行的代码 if expression: expr_true_suite 条件表达式可以是多重的 通过布尔操作符 and or not来…

【maven3学习之三】maven构建一个简单的Hello World

2019独角兽企业重金招聘Python工程师标准>>> 在写之前我先需要配置一下setting.xml。 首先是localRepository&#xff0c;默认情况下是【你的用户目录】/.m2/repository作为本地库的目录&#xff0c;但是我希望将其放在D:\maven_localRepository的目录下面。 如果…

全国计算机等级考试题库二级C操作题100套(第18套)

第18套&#xff1a; 给定程序中&#xff0c;函数fun的功能是&#xff1a;将形参s所指字符串中的所有字母字符顺序前移&#xff0c;其他字符顺序后移&#xff0c;处理后新字符串的首地址作为函数值返回。 例如&#xff0c;s所指字符串为:asd123fgh543df,处理后新字符串为:asdfgh…

python营销骗局_python案例:金融营销活动中欺诈用户行为分析

首先&#xff0c;数据导入 1 importnumpy as np2 importpandas as pd3 from collections importCounter4 importmatplotlib.pyplot as plt5 from pymining importitemmining,assocrules,perftesting,seqmining6 importpyecharts as pe7 rtpd.read_csv(r"E:\transaction_tr…

java 重定向 https_使用简单身份验证从HTTP重定向到HTTPS

我希望得到一些关于如何使用带有ember-simple-auth的ember初始化程序将用户从HTTP重定向到HTTPS的建议 .import ENV from cio/config/environmentSSLInitializer name: sslbefore: simple-auth-cookie-storeinitialize: (container, application) ->application.deferReadin…

你真的会数钱吗?

本文已迁移至&#xff1a;http://thinkinside.tk/2013/01/01/money.html 快年底了&#xff0c;假如你们公司的美国总部给每个人发了一笔201212.21美元的特别奖金&#xff0c;作为程序员的你&#xff0c; 该如何把这笔钱收入囊中&#xff1f; Table of Contents 1 美元&#xff…

Maven 系统环境变量配置

Download http://maven.apache.org/download.cgi http://mirrors.shu.edu.cn/apache/maven/maven-3/3.5.4/binaries/apache-maven-3.5.4-bin.zip 环境变量 1.添加 MAVEN_HOME&#xff1a; 变量名&#xff1a;MAVEN_HOME  变量值&#xff1a;C:\Program\apache-maven-3.5.4 注…

全国计算机等级考试题库二级C操作题100套(第19套)

第19套&#xff1a; 程序通过定义学生结构体变量&#xff0c;存储了学生的学号、姓名和3门课的成绩。函数fun的功能是将形参a所指结构体变量s中的数据进行修改,并把a中地址作为函数值返回主函数&#xff0c;在主函数中输出修改后的数据。 例如&#xff1a;a所指变量s中的学号…

eclipse中文乱码解决_解决git status显示中文文件名乱码问题

使用 git status 查看本地有改动但未提交的中文文件名时&#xff0c;发现会显示为一串数字&#xff0c;没有显示中文的文件名。具体如下所示&#xff1a;$ git status# 位于分支 master# 尚未暂存以备提交的变更:# (使用 "git add ..." 更新要提交的内容)# (使用 &qu…

MongoDB 3.X 用户权限控制

摘要&#xff1a; MongoDB 3.0 安全权限访问控制&#xff0c;在添加用户上面3.0版本和之前的版本有很大的区别&#xff0c;这里就说明下3.0的添加用户的方法。 环境、测试&#xff1a; 在安装MongoDB之后&#xff0c;先关闭auth认证&#xff0c;进入查看数据库&#xff0c;只有…

oracle和sql server取第一条记录的区别以及rownum详解

我们知道学生可能有重名的情况&#xff0c;那么当重名的时候假设只需要取得重名结果集中的第一条记录。 sql server:select top(1) num,Name from M_Student where name xy Oracle:select num,Name from M_Student where name xy and rownum < 1 对于rownum在oracle的使用…

全国计算机等级考试题库二级C操作题100套(第20套)

第20套&#xff1a; 给定程序中&#xff0c;函数fun的功能是&#xff1a;计算形参x所指数组中N个数的平均值&#xff08;规定所有数均为正数&#xff09;,将所指数组中小于平均值的数据移至数组的前部&#xff0c;大于等于平均值的数据移至x所指数组的后部&#xff0c;平均值作…

java enum 变量_java枚举使用详解

package com.ljq.test;/*** 枚举用法详解** author jiqinlin**/public class TestEnum {/*** 普通枚举** author jiqinlin**/public enum ColorEnum {red, green, yellow, blue;}/*** 枚举像普通的类一样可以添加属性和方法&#xff0c;可以为它添加静态和非静态的属性或方法**…

c#小游戏_C#小游戏—钢铁侠VS太空侵略者

身为漫威迷&#xff0c;最近又把《钢铁侠》和《复仇者联盟》系列又重温了一遍&#xff0c;真的是印证了那句话&#xff1a;“读书百遍&#xff0c;其意自现”。看电影一个道理&#xff0c;每看一遍&#xff0c;都有不懂的感受~ 不知道大伙是不是也有同样的感受&#xff0c;对于…