从零开始学多线程之线程安全(一)

 最近在复习、整理之前学习的多线程的知识,本着燃烧自己,照亮他人的想法,把自己整理的一些关于多线程的学习笔记、心得分享给大家.

 

博主准备把自己关于多线程的学习笔记写成三个部分分享给大家: 基础、实战、测试&优化

 

这三个部分是一环扣一环的.

 

1.基础: 多线程操作的对象必须是线程安全的,所以构建线程安全的对象是一切的基础.这一部分讲的就是如何构建线程安全的类,和一些多线程的基础知识.

 

2. 实战: 构建好了线程安全的类,我们就可以用线程/线程池,去构建我们的并发程序了,如何执行任务?如何关闭线程池?如何扩展线程池?这里都会给你答案

 

3. 测试&优化: 构建好的程序会不会发生死锁? 如何优化程序? 如何知道运行的结果是否正确? 这一部分会 一 一为你解答.

 

好了废话不多说,本篇博客是系列的第一篇,我们来讲述一下线程安全.

 

 

线程安全

在多线程环境下,保证线程访问的数据的安全格外重要.编写线程安全的代码,本质上就管理状态的访问,而且通常是共享的可变的状态. 

 

状态:可以理解为对象的成员变量.

共享: 是指变量可以被多个线程访问

可变: 是指变量的值在生命周期内可以改变.

保证线程安全就是要在不可控制的并发访问中保护数据.

如果对象在多线程环境下无法保证线程安全,就会导致脏数据和其他不可预期的后果

 

有很多在单线程环境下运行良好的代码,在多线程环境下却有问题.例如自增操作:

复制代码
public class Increment {     private int num = 0;      public void doSomething(){         //do something         num++;     } }
复制代码

每次调用doSomething()方法的时候,num都会执行自增操作.但是在多线程环境下,这段代码是有问题的.

原因在于num++并不是原子操作,而是由三个离散操作组合而来的:"读-改-写",读取当前的值,加1,写入变量.

可能会出现某一时刻,两个线程同时读到num的数值,然后分别+1,分别写入.这样其中一次计数就不存在了.

 

有一个专门形容这类情况的名词,叫竞争条件

当计算的正确性依赖于运行时相关的时序或者多线程的交替时,会产生竞争条件.

我对竞争条件的理解就是,多个线程同时访问一段代码,因为顺序的问题,可能导致结果不正确,这就是竞争条件.

 

"检查-再运行",也是一种竞争条件.

复制代码
public class Singleton {     private Singleton singleton;      private Singleton() {     }      public Singleton getSingleton

                    
                
50000+
5万行代码练就真实本领
17年
创办于2008年老牌培训机构
1000+
合作企业
98%
就业率

联系我们

电话咨询

0532-85025005

扫码添加微信