【从入门到放弃-Java】并发编程-线程安全

?线程在同一时间段内“同时”运行。

如今,多处理器系统已经变得流行,多线程可以发挥其优势,例如:一个8核cpu服务器,如果只有单线程,就会有7个处理器闲置,只能打出服务器8个点其中一项功能(忽略其他资源使用情况)。

同时,使用多线程可以简化复杂任务的处理逻辑,并降低业务模型的复杂性。

因此,并发编程在提高服务器资源利用率,提高系统吞吐量和降低编码难度方面起着重要作用。

线程安全。

当线程同时执行时,由于CPU的调度,线程将交替执行。如以下示例所示

执行完成后,count的值每次不等于,并且将小于,因为thread1和thread2可能交替。

如图所示:

时间t1: thread1读取计数=100

T2时间: thread2读取计数=100

T3时间: thread1计数+ 1

T4时间: thread2计数+ 1

T5时间: thread1将101写入计数

T5时间: thread2将101写入计数

因为count ++不是原子操作,所以它实际上执行了三个步骤:

1,获取count的值

2,添加计数1

3.将计算结果写入计数

因此,当并发执行时,两个线程同时读取,可能读取相同的值,添加一个相同的值,导致结果不符合预期,这是线程不安全。

线程安全:当多个线程访问一个类时,无论运行时环境使用的调度方法或这些线程如何交替,并且调用不需要额外的同步,该类将正常运行。然后,这个类被称为线程安全的。

线程安全问题的主要原因是共享内存可以被多个线程读取和写入,因为读取和修改的时间不确定,导致线程读取过期数据,并将其写回共享在基于脏数据处理之后。记忆产生了错误的结果。

件。

件类型:

件是否为真。根据这一观察,采取相应的行动,但实际上,在观察该结果与采取相应行动之间,观察结果可能会改变并变得无效,导致所有后续行动变得不可预测。 (例如延迟初始化)

读 - 修改 - 写:根据对象之前的状态定义对象状态的转换。但是,在读取结果和修改结果之间可能已经更改了对象。这将导致基于错误数据修改的错误结果并将被写入。 (如增量操作)

发布和逃避

发布:允许在当前范围之外的代码中使用对象。如果将对象的引用保存到其他代码可以访问它的位置,则以非私有方法返回引用,并将引用传递给其他类的方法。如:

这里发布了学生对象。

转义:当一个不应发布的对象被释放时,它被称为转义。如

这里的名称最初是私有的,但是由getString方法发布,它可以被视为转义。

线程关闭

线程关闭对象只能由一个线程拥有,该对象包含在该线程中,并且只能修改此对象。

线程闭合意味着不共享数据,只在单个线程中访问数据。这是实现线程安全的最简单方法之一。

要实现线程关闭,您可以传递:

临时线程关闭:维护线程关闭的责任完全由成熟的实现承担。

堆栈闭包:可以通过存储在执行线程堆栈中的本地变量访问该对象,并且其他线程无法访问该对象。

ThreadLocal类:将共享的全局变量转换为ThreadLocal对象。当线程终止时,这些值被垃圾收集。

只读共享

多个线程可以同时访问共享对象而无需额外的同步,但没有线程可以修改它们。共享对象包括不可变对象和事实不可变对象。

不可变对象:如果在创建对象后无法修改该对象,则该对象是不可变对象。不可变对象必须是线程安全的。

线程安全共享

线程安全对象在内部进行同步,因此可以通过对象的公共接口访问多线程,而无需自行同步。

受保护的对象

只能通过持有特定锁来访问受保护对象。这是为了通过锁定机制确保物体的可见性和原子性。

内置锁:使用synchronized关键字同步代码块。线程在进入同步块之前自动获取锁定,并在退出同步块时自动释放锁定。内置锁是互斥锁。

可重入锁定:当线程视图获得已经保持的锁定时,它会增加锁定计数器并在释放锁定时将计数器减1。当计数器为0时,释放锁定

易失性:访问volatile变量时,它不会锁定并且不会阻止线程执行。他只确保变量的可见性,这是一种比同步更轻量级的同步机制。

本文主要记录了前面章节《Java并发编程实站》中与并发编程相关的一些概念。简要介绍了线程安全,锁机制等,我们将深入介绍JUC源代码,深入理解并发编程的知识。

注意:本文主要源自《Java并发编程实战》的学习笔记。

作者:aloof _

阅读原文

本文是云栖社区的原创内容,未经许可,不得转载。

银河电子游艺