了解Java线程锁之前,先理解线程和进程的定义。进程是操作系统分配资源(CPU)的基本单位,线程是CPU执行的基本单位,一个进程可拥有多个线程,同进程间的多个线程共享分配给进程的资源。比如启动JVM时,会拥有一个进程,JVM处理并发请求的线程共享JVM的堆内存资源。

  进程间的通信:网络通信,比如RPC,MQ,Socket。

  线程间的通信:由于多线程共享地址空间和数据空间,因此同进程间的多个线程的通信是任意线程数据可以直接提供其他线程使用,而不必通过操作系统。

  Java线程的状态:初始(New),运行(Runnable),阻塞(Blocked),等待(Waiting),超时等待(Time_Waiting),终止(Teminate)。

  1. 初始:新创建的一个线程对象,但还没有调用start()方法。

  2. 运行:Java线程中将就绪(ready)和运行中(Running)俩种状态笼统称为“运行”。

  3. 阻塞:表示线程阻塞于锁。

  4. 等待:进入该状态的线程需要其他线程作出一些特定动作(通知或中断)来激活或结束。

  5. 超时等待:该状态等同于Waiting,它可以在制定的时间内自行返回,比如sleep()方法。

  6. 终止:表示该线程已经执行完毕

  通过线程的6大状态,能看出线程锁主要出现在阻塞(Blocked),什么情况下会用到线程锁?比如并发情况下为了控制资源争抢问题或者实现互斥效果,会进行locked,也就是把并发控制为同步。

  既然线程锁已能实现同步控制,为什么还要衍生出分布式锁?因为所谓的线程锁解决的是同一个进程中的并发锁问题,不同进程中存在资源可见性的问题。进程间的资源是不共享的,也就是不可见的。比如在不同端口启动多个JVM(多个进程),它们之间的共享资源(内存)和线程锁都是互不可见的。从而分布式系统中,也是在分布在不同机器中,同进程的线程锁是无法控制并发问题的。

  分布式锁应该具备的条件:

  1. 在分布式系统环境下,一个方法在同一时间只能被一个机器的一个线程执行; 
  2. 高可用的获取锁与释放锁; 
  3. 高性能的获取锁与释放锁; 
  4. 具备可重入特性; 
  5. 具备锁失效机制,防止死锁; 
  6. 具备非阻塞锁特性,即没有获取到锁将直接返回获取锁失败。

  如何在分布式系统中解决最基本的资源争抢或者数据覆盖的问题,理论上来说解决此问题,最基本需解决锁可见性的问题,也就是共享资源。比如基于数据库的锁机制,基于缓存(redis)的分布式锁,以及基于zookeeper实现的分布式锁。

  1. 基于数据库的锁机制实现的分布式锁

  作为数据库本身已有一套健全的锁机制(更新),同时是基于外部的磁盘存储的逻辑(另外一个进程),完全符合分布式锁的需求,但由于锁资源存储在磁盘中,需进行I/O操作,因此相对来说性能不高。

  比如:select * from tb_lock where id = 3 for update,当执行这个语句时,数据库会自动对id=3这一行数据加行级锁(id为主键,否则为表级锁),其它事务必须等待此次事务提交或回滚后才能执行。

  2. 基于缓存(redis)实现的分布式锁

  由于redis的单进程单线程的原理,同时也时外部缓存的存储逻辑,也是能作为分布式锁的底层基础。同时expire的过期功能,又完美的解决了特殊原因导致锁无法释放的问题。

  github上的redisson开源项目已实现了分布式锁功能,同时也解决了redis的重入锁问题。也可通过LUA脚本+redis实现单线程事务控制。

  3. 基于zookeeper实现的分布式锁

  基于zookeeper临时有序节点的大致思想:每个客户端对某个方法加锁时,在zookeeper上的与该方法对应指定节点的目录下,生成一个唯一的瞬时节点。判断是否获取锁的逻辑是只需要判断有序节点序号最小的一个。当释放锁的时,只需将这个瞬时节点删除即可。同时,其可避免服务宕机导致的锁无法释放,而产生的死锁问题。

  

Java线程锁&分布式锁的理解及应用的更多相关文章

  1. Java 线程安全 与 锁

    Java 线程安全 与 锁 多线程内存模型 线程私有栈内存 每个线程 私有的内存区域 进程公有堆内存 同一个进程 共有的内存区域 为什么会有线程安全问题? 多个线程同时具有对同一资源的操作权限,又发生 ...

  2. Java使用Redisson分布式锁实现原理

    本篇文章摘自:https://www.jb51.net/article/149353.htm 由于时间有限,暂未验证 仅先做记录.有大家注意下哈(会尽快抽时间进行验证) 1. 基本用法 添加依赖 &l ...

  3. 【Thread】java线程之对象锁、类锁、线程安全

    说明: 1.个人技术也不咋滴.也没在项目中写过线程,以下全是根据自己的理解写的.所以,仅供参考及希望指出不同的观点. 2.其实想把代码的github贴出来,但还是推荐在初学的您多亲自写一下,就没贴出来 ...

  4. Java线程安全与锁优化,锁消除,锁粗化,锁升级

    线程安全的定义 来自<Java高并发实战>"当多个线程访问一个对象的时候,如果不用考虑这些线程在运行时环境下的调度和交替执行,也不需要进行额外的同步,或者在调用方法的时候进行任何 ...

  5. Java线程安全与锁优化

    线程安全的严谨定义: 当多个线程访问一个对象时,如果不用考虑这些线程在运行时环境下的调度和交题执行,也不需要进行额外的同步,或者调用方法进行其他任何操作,调用这个对象的行为都可以或者正确的结果,那么这 ...

  6. 【Java线程安全】锁

    Java都有哪些锁? synchronized 和 reentranlock是最常见的,其中前者又JVM提供实现,后者有专门对应的java.util.concurrent包提供:同时后者功能更加丰富. ...

  7. Java线程同步与锁

    一.synchronized synchronized锁什么?锁对象.可能锁对象包括: this, 临界资源对象,Class类对象. 1,同步方法 synchronized T methodName( ...

  8. java实现Redis分布式锁

    网上到处都是分布式锁的代码,基本都是通过setNX 和 expire 这两个不是原子操作,肯定会有问题,不乏好多人通过用setNX的value当做过期时间来弥补等等.但是好像都不太好,或者多少有点问题 ...

  9. 终极锁实战:单JVM锁+分布式锁

    目录 1.前言 2.单JVM锁 3.分布式锁 4.总结 =========正文分割线================= 1.前言 锁就像一把钥匙,需要加锁的代码就像一个房间.出现互斥操作的场景:多人同 ...

随机推荐

  1. 简单的搭mysql开发环境

    所需软件  环境win8 64bit mysql5.7.16winx64.zip mysql-workbench-community-6.3.5-win32.zip 安装完了之后到mysql/bin下 ...

  2. 浅谈js设计模式之策略模式

    策略模式有着广泛的应用.本节我们就以年终奖的计算为例进行介绍. 很多公司的年终奖是根据员工的工资基数和年底绩效情况来发放的.例如,绩效为 S的人年终奖有 4倍工资,绩效为 A的人年终奖有 3倍工资,而 ...

  3. 洛谷P3396哈希冲突

    传送门啦 非常神奇的分块大法. 这个题一看数据范围,觉得不小,但是如果我们以 $ \sqrt(x) $ 为界限,数据范围就降到了 $ x < 400 $ 我们设数组 $ f[i][j] $ 表示 ...

  4. 洛谷P2016战略游戏

    传送门啦 战略游戏这个题和保安站岗很像,这个题更简单,这个题求的是士兵人数,而保安站岗需要求最优价值. 定义状态$ f[u][0/1] $ 表示 $ u $ 这个节点不放/放士兵 根据题意,如果当前节 ...

  5. 奇妙的CSS之伪类与伪元素

    我们都知道,在CSS中有很多选择器,例如id(#), class(.),属性[attr],这些虽然可以满足一些需要,但有时候还力有未逮.伪类和伪元素就提供了一个有益的补充,可以使我们更高效编码.伪类和 ...

  6. SQL CAST与CONVERT区别

    CAST 和 CONVERT 将某种数据类型的表达式显式转换为另一种数据类型.CAST 和 CONVERT 提供相似的功能. 语法 使用 CAST: CAST ( expression AS data ...

  7. Apache Kylin安装部署

    0x01 Kylin安装环境 Kylin依赖于hadoop大数据平台,安装部署之前确认,大数据平台已经安装Hadoop, HBase, Hive. 1.1 了解kylin的两种二进制包 预打包的二进制 ...

  8. 什么是 CLR(转)

    CLR(公用语言运行时)和Java虚拟机一样也是一个运行时环境,它负责资源管理(内存分配和垃圾收集),并保证应用和底层操作系统之间必要的分离..NET提供了一个运行时环境,叫做公用语言运行时(Comm ...

  9. Pg168—2题 修改

    package org.hanqi.pn0120; public class JuXing { JuXing(double chang,double kuan) { this.chang=chang; ...

  10. 【LOJ】#2056. 「TJOI / HEOI2016」序列

    题解 这个我们处理出来每一位能变化到的最大值和最小值,包括自身 然后我们发现 \(f[i] = max(f[i],f[j] + 1) (mx[j] <= a[i] && a[j] ...