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资源


目录
相关文章
|
23小时前
|
存储 设计模式 并行计算
CopyOnWriteArrayList:深入理解Java中的线程安全List原理和应用
CopyOnWriteArrayList:深入理解Java中的线程安全List原理和应用
7 0
|
1天前
|
Java 测试技术 开发者
Java并发编程:深入理解线程池
本文将带领读者深入了解Java中的线程池,探索其内部机制、使用场景以及如何有效地利用线程池来提高程序的性能和可维护性。我们将通过实例演示如何创建和配置线程池,并讨论常见的并发模式和最佳实践。文章旨在为开发者提供实用的线程池应用知识,帮助他们在面对多线程编程挑战时,能够设计出更加高效和稳定的系统。
|
1天前
|
安全 Java 开发者
如何在Java中实现线程安全的单例模式
如何在Java中实现线程安全的单例模式
|
2天前
|
缓存 监控 安全
深入理解Java中的线程池和并发编程
深入理解Java中的线程池和并发编程
|
2天前
|
设计模式 安全 Java
如何在Java中实现线程安全的单例模式
如何在Java中实现线程安全的单例模式
|
27天前
|
存储 安全 Java
深入理解Java并发编程:线程安全与锁机制
【5月更文挑战第31天】在Java并发编程中,线程安全和锁机制是两个核心概念。本文将深入探讨这两个概念,包括它们的定义、实现方式以及在实际开发中的应用。通过对线程安全和锁机制的深入理解,可以帮助我们更好地解决并发编程中的问题,提高程序的性能和稳定性。
|
1月前
|
安全 Java 容器
Java一分钟之-并发编程:线程安全的集合类
【5月更文挑战第19天】Java提供线程安全集合类以解决并发环境中的数据一致性问题。例如,Vector是线程安全但效率低;可以使用Collections.synchronizedXxx将ArrayList或HashMap同步;ConcurrentHashMap是高效线程安全的映射;CopyOnWriteArrayList和CopyOnWriteArraySet适合读多写少场景;LinkedBlockingQueue是生产者-消费者模型中的线程安全队列。注意,过度同步可能影响性能,应尽量减少共享状态并利用并发工具类。
34 2
|
1月前
|
安全 Java
Java中的并发编程:理解并发性与线程安全
Java作为一种广泛应用的编程语言,在并发编程方面具有显著的优势和特点。本文将探讨Java中的并发编程概念,重点关注并发性与线程安全,并提供一些实用的技巧和建议,帮助开发人员更好地理解和应用Java中的并发机制。
|
1月前
|
缓存 安全 Java
Java并发编程中的线程安全问题及解决方法
在Java编程中,线程安全是一个至关重要的问题,特别是在并发编程中。本文将探讨Java并发编程中常见的线程安全问题,包括数据竞争、死锁和内存可见性,并介绍了相应的解决方法,如使用同步锁、并发容器和原子类等技术,以确保多线程环境下程序的正确性和性能。
16 2
|
1月前
|
安全 Java 容器
Java并发编程:实现高效、线程安全的多线程应用
综上所述,Java并发编程需要注意线程安全、可见性、性能等方面的问题。合理使用线程池、同步机制、并发容器等工具,可以实现高效且线程安全的多线程应用。
23 1