Java多线程- synchronized关键字总结

简介: Java多线程- synchronized关键字总结

线程锁的概要

     首先对于锁的条件和要点进行一个总结:

  • 锁使用来保护代码片段的, 以保证多线程的安全性, 一次只允许一个线程执行被保护的代码.
  • 锁可以管理视图进入被保护代码的线程, 提高多线程安全
  • 一个锁可以有一个或多个关联的条件对象

对于synchronized来说, 如果它修饰的是方法, 那么他保护的代码段将是整个方法

Synchronized关键字

       结合锁策略, 可以得出以下结论:

  1. synchronized开始是乐观锁, 如果冲突太频繁了, 那么synchronized就升级为悲观锁
  2. synchronized开始是轻量级锁, 如果单个线程占用synchronized锁的时间长了, 就会变成重量级锁.
  3. 此处的轻量级锁和自旋锁有重叠的部分
  4. synchronized是一种不公平的锁
  5. synchronized是一种可重入锁
  6. synchronized不是读写锁

synchronized加锁过程

  1. 首先对一个无锁的代码段进行加锁,  这个锁会进入偏向锁的状态, 此处的偏向锁不是真正的加锁, 而是给这个锁做一个标记, 表示这个锁属于哪个线程, 如果后续没有线程来抢锁, 那么就不会进行其他同步操作.  如果有的话, 那么这个锁就会升级为真正的锁, 进入一种以自旋锁为基础的轻量级锁状态
  2. 进入轻量级锁, 此处的轻量级锁是通过CAS实现的, 轻量级锁适用于抢锁比较少的多线程环境, 基于自旋锁, 如果其他线程来抢锁就会阻塞等待, 并且在极短时间内进行第二次访问, 直到拿到锁. 但是如果锁长时间没有释放就会造成CPU空转, 浪费CPU资源. 所以如果有多个线程频繁的抢锁, 锁就会升级为重量级锁. 让线程放弃CPU, 进入内核态,此时有操作系统来通知线程这个锁是否被释放, 然后再来调度这些抢锁的线程.
  3. 轻量级锁的竞争激烈后, 就会升级为重量级锁,如果该锁被占用, 则加锁失败. 此时线程进入锁的等待队列, 挂起. 等待被操作系统唤醒.经过一段时间后, 这个锁被其他线程释放了, 操作系统也想起了这个挂起的线程, 于是唤醒这个线程, 尝试重新获取锁.

synchronized锁优化

       锁消除

       遵循于非必要不加锁的规则, synchronized实现了锁消除机制, 也就是在非多线程情况下, synchronized会自动识别线程情况, 自动消除掉不必要的锁,

       例如我们常用的线程安全的StringBuffer, 但是如果在单线程使用, 那么就会在编译的时候去除synchronized关键字, 来减少非必要的开销.

StringBuffer sb = new StringBuffer();
sb.append("a");
sb.append("b");
sb.append("c");
sb.append("d");

此处每次的append操作都会加锁, 造成了非必要的资源浪费

       锁粗化

       在一段代码中, 可能存在两个被保护的代码段, 如下:

如果这两个代码段(代码段1和代码段2)之间, 不存在锁竞争的情况话, 就可以省去中间的解锁和加锁, 这样就避免的多余的加锁解锁操作, 节约了CPU资源


目录
相关文章
|
1月前
|
JSON 网络协议 安全
【Java】(10)进程与线程的关系、Tread类;讲解基本线程安全、网络编程内容;JSON序列化与反序列化
几乎所有的操作系统都支持进程的概念,进程是处于运行过程中的程序,并且具有一定的独立功能,进程是系统进行资源分配和调度的一个独立单位一般而言,进程包含如下三个特征。独立性动态性并发性。
130 1
|
1月前
|
JSON 网络协议 安全
【Java基础】(1)进程与线程的关系、Tread类;讲解基本线程安全、网络编程内容;JSON序列化与反序列化
几乎所有的操作系统都支持进程的概念,进程是处于运行过程中的程序,并且具有一定的独立功能,进程是系统进行资源分配和调度的一个独立单位一般而言,进程包含如下三个特征。独立性动态性并发性。
150 1
|
2月前
|
数据采集 存储 弹性计算
高并发Java爬虫的瓶颈分析与动态线程优化方案
高并发Java爬虫的瓶颈分析与动态线程优化方案
Java 数据库 Spring
130 0
|
2月前
|
算法 Java
Java多线程编程:实现线程间数据共享机制
以上就是Java中几种主要处理多线程序列化资源以及协调各自独立运行但需相互配合以完成任务threads 的技术手段与策略。正确应用上述技术将大大增强你程序稳定性与效率同时也降低bug出现率因此深刻理解每项技术背后理论至关重要.
212 16
|
Java
Java关键字 —— static 与 final 详细解释!一看就懂 有代码实例运行!
这篇文章详细解释了Java中static和final关键字的用法,包括它们修饰类、方法、变量和代码块时的行为,并通过代码示例展示了它们的具体应用。
835 0
Java关键字 —— static 与 final 详细解释!一看就懂 有代码实例运行!
|
Java 数据安全/隐私保护
Java基础手册二(类和对象 对象创建和使用 面向对象封装性 构造方法与参数传递 this关键字 static关键字 继承 多态 方法覆盖 final关键字 访问控制权限修饰符)
Java基础手册二(类和对象 对象创建和使用 面向对象封装性 构造方法与参数传递 this关键字 static关键字 继承 多态 方法覆盖 final关键字 访问控制权限修饰符)
131 0
Java里的关键字 __final
Java里的关键字 __final
|
安全 Java 编译器
【Java用法】Java关键字 —— final的用法
【Java用法】Java关键字 —— final的用法
190 0
|
Java C++ Python
Java 的关键字 final 和 static
Java 中最经典 final 修饰的类就是 String 了,它无法被任何类继承,不仅仅是为了保证 String 的不变性,同时在早期的 Java 版本中会将 final 修饰的方法转化为内嵌调用,提高程序性能(后来的 Java 会自动进行优化,不需要显式地用 final 修饰)。不过要注意的一点是,final 修饰的引用变量,其指向的对象的内容是可以被改变的。final 修饰符可以用来修饰类、方法和变量,final 修饰的类不能够被继承,修饰的方法不能被继承类重新定义,修饰的变量为常量,是不可修改的。
262 0