IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> Java多线程中的 Lock synchronized 和 volatile -> 正文阅读

[Java知识库]Java多线程中的 Lock synchronized 和 volatile

0. 写在前面

Java 多线程编程中 Lock 的概念和synchronizedvolatile关键字是经常遇到的内容或者说知识点,本文是我最近学习多线程的个人总结,会说明这三者涉及的一些基础概念,所以它们不是很全面,跳动性会有点大,参考资料会在文章结尾给出。

前提条件

  • 最基本的,我觉得你需要了解线程的概念,这是最低要求了🤣。

1. 线程安全

线程安全是我们最常听到的名词,我直接拿出《Concurrency in Java》中对其的定义:

A class is thread‐safe if it behaves correctly when accessed from multiple threads, regardless of the scheduling or interleaving of the execution of those threads by the runtime environment, and with no additional synchronization or other coordination on the part of the calling code.
当多个线程访问某个类时,不管运行时环境采用何种调用方式或者这些线程将如何交替执行,并且在主调代码中不需要任何额外的同步或协同,这个类都能表现出正确的行为,那么就称这个类时线程安全的。

你会发现,线程安全被限制在类级别(class level),我们也常听到某某某类不是线程安全的。举个例子,假使现在我们有一个ArrayList对象,当多个线程同时访问/操作该对象时,很有可能出问题,比如都调用其add方法,list 对象中的元素很有可能出现不一致的情况,当然还有许许多多其它的场景展示非线程安全。如果某类是线程安全的,那么你就可以放心地去使用它,而无需花费额外的精力保证线程安全。

补充:文章中多次提到的访问(access),比如访问某对象,这其中包含调用该对象的方法,在此,你可以理解为读写行为都会有。

当我们使用非线程安全的类时,为了保证正确的结果,就需要增加一些额外的操作,比如加锁,上面提到的协同(coordination),我现在还未涉及到,暂不做讨论。看起来,加锁似乎是万能的,因为当许多事情并行/异步运行时,加锁使得我们访问某个对象可以是串行/同步的。但是,从哲学方面考虑,事物总是有两面性,当在某些方面突出时,它肯定牺牲了其它的资源。加锁虽然可以解决我们遇到的绝大部分非线程安全的问题,但也带来了更大的开销,效率更低,所以我们需要一些更轻量的方式来满足不同的场景。

来到正题,synchronized使lock()/unlock()更为方便,volatile仅仅保证可见性,并不保证原子性。我们在后面做更详细的介绍,换句话说,此时你可以把这篇博客关掉了,因为文章中心句就是前面那一句,你已经得到了你想要的🤪。

2. 锁 Lock

此时,你可以找到Lock接口的源码,它在java.util.concurrent.locks包下,使用它非常简单:

Lock l = ...;
l.lock();
try {
    // access the resource protected by this lock
} finally {
    l.unlock();
}

比较常用的锁有ReentrantLockReentrantReadWriteLock,对于前者,使用方式和👆🏻相同,当某个线程中的ReentrantLock(可重入锁)对象请求锁成功后,它可以再次调用其lock()方法请求锁,成功后,锁的被拥有数(hold count)加1,同时,你还可以配合Condition一起使用,在此不做深入。对于后者,它基本支持前者的语义,场景更定制化,效率有时会更高,它包含两个内部类:ReadLockWriteLock,使用方式依然和👆🏻相同,其中写锁和其它锁互斥,读锁和读锁之间共享,即不会出现阻塞的情况。

3. synchronized

每个对象内部都有一个隐式的可重入锁,使用synchronized,我们不必再去创建锁(因为已经有一个可以用了),也不必去lock()unlock(),你可以使用synchronized包裹一个方法或是一段代码块:

void method() {
    // 此时会请求 a 的锁
    synchronized (a) {
        // some actions
    }
}
// 另一种方式
class A {
    // 此时会请求 A 的实例化对象的锁
    synchronized void method() {
       ...
    }
}
// 也可以只包裹代码块
void method() {
    // some preparations
    synchronized (a) {
        // some actions
    }
    // other actions
}

你注意到synchronized后会跟一个参数,它可以是某个对象,此时会请求该对象的锁;也可以是类名,像是synchronized (A.class),此时请求的是该类的锁。需要注意的是,如果参数改变,这可能会是对象改变,这样同步就会失效,因为对象不是同一个,请求的对象的锁自然也不是同一个,看一下下面例子:

String str = "watman";
...
synchronized (str) {
   // some actions
}
// 如果 str 在某处被改变
str = "badman";
synchronized (str) {
   // some actions
}
// 此时不能保证是同步的

4. volatile

因为线程会对涉及的变量做本地拷贝或者本地副本(local copy),这样数据可能会与其他线程中保存的数据不同。多个线程访问相同对象时,可能出现数据不一致的情况,volatile是域修饰符(field modifer),比如

class Menagerie {
    public volatile Integer count;
}

volatile会使其修饰的属性在必要的时候与主内存中的值一致,我们称其为可见性,有些时候,满足可见性就能使我们的类线程安全,当然,有些时候不能。volatile不保证原子性,它的意思是执行volatile修饰的属性的某个操作时,属性的值会在执行的过程中被改变。所以,对于需要原子性的场景,你还需要同步。你可能会问,同步也需要保证可见性呀!事实是,同步同时满足可见性和原子性,同步块内的代码,或者锁包裹内的代码也会在必要的时候保证其中的值一致。

5. 小结

本文对 Java 多线程编程中常用的Locksynchronizedvolatile做了一个大致的介绍,包含一些使用方式和注意事项。

参考资料

  1. 《Java多线程编程核心技术》:非常不推荐,自己非常后悔买的一本书,因为它真的很水,你可以在豆瓣上看一下它的评价,以及仔细的看一下它的目录;
  2. 《Java核心技术卷一》并发部分
  3. 《深入理解JVM虚拟机》并发部分
  4. 一些博客
  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2021-11-29 16:10:49  更:2021-11-29 16:12:02 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 3:25:42-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码