Java并发编程《并发编程实战》-2021-02-05

简单说一下线程的好处:

单线程:可以理解为一个人干多件事,我刷碗就不能烧饭必须先刷碗之后再去烧饭,执行起来就很慢。

多线程:多个人干配合干不同的事情,提高了效率,一个人烧饭,一个人刷碗,烧好饭碗也好了可以直接出锅了。

public class UnsafeSequence {

    private int value;
    /**
     * 返回一个唯一的数值。
     */
    public int getNext() {
        return value++;
    }

}

看一串代码, 一个线程执行不存在问题,但是存在多个线程的问题。

多个线程对一个对象访问,不同的线程相互不打扰同时访问getNext(); value++; 从Java代码中看起来是一条指令,实际上在编译成字节码的时候,是三条,分别是读取value,准备常量1,写入value。

这样的操作就可能在执行一个步骤的时候被其它线程打断,就会存在线程安全或者说共享数据的脏读脏写的问题。

扩充知识:线程存在各种指令,CPU会分配给不同的线程一段执行时间称之为时间片,每一个线程执行完之后就进行切换到其它线程进行执行代码块。程序并不是共同前进的。

所以这样的切换间隙就会存在共享数据的安全问题,比如:Thread1,getNext() 获取到了数据,这个时候发生了切换到Thread2,Thread2也getNext() 但是这个时候Thread1还没有开始写入,而Thread2继续执行写入数据。切换为Thread1,Thread1也开始自加1然后写入,但是这个时候实际上是应该+2,但是因为切换的问题,读取和写入不在一个点上导致的这个数据安全问题。

具体情况可以看这一张图,AB两个线程,读取的时候切换,写入的时候切换,然后写入的都是10,正常逻辑应该为11,就导致了数据不安全。

在图中给出了不同线程之间的一种交替执行情况。在图中,执行时序按照从左到右的顺序递增,每行表示一个线程的动作。这些交替执行示意图给出的是最糟糕的执行情况,目的是为了说明:如果错误地假设程序中的操作将按照某种特定顺序来执行,那么会存在各种可能的危险。

public class UnsafeSequence {

    private int value;
    /**
     * 返回一个唯一的数值。
     */
    public synchronized int getNext() {
        return value++;
    }

}

这是一段西安城安全的ID生成器。

如果没有同步,那么无论是编译器、硬件还是运行时,都可以随意安排操作的执行时间和顺序,例如对寄存器或者处理器中的变量进行缓存,而这些被缓存的变量对于其他线程来说是暂时(甚至永久)不可见的。虽然这些技术有助于实现更优的性能,并且通常也是值得采用的方法,但它们也为开发人员带来了负担,因为开发人员必须找出这些数据在哪些位置被多个线程共享,只有这样才能使这些优化措施不破坏线程安全性。

造成线程不安全的主要原因就是多个线程访问,特别是对共享的(Shared)和可变的(Mutable)状态的访问。

从非正式的意义上来说,对象的状态是指存储在状态变量(例如实例或静态域)中的数据。对象的状态可能包括其他依赖对象的域。例如,某个HashMap的状态不仅存储在HashMap对象本身,还存储在许多Map.Entry对象中。在对象的状态中包含了任何可能影响其外部可见行为的数据。

“共享”意味着变量可以由多个线程同时访问,而“可变”则意味着变量的值在其生命周期内可以发生变化。

一个对象是否需要是线程安全的,取决于它是否被多个线程访问。这指的是在程序中访问对象的方式,而不是对象要实现的功能。要使得对象是线程安全的,需要采用同步机制来协同对对象可变状态的访问。如果无法实现协同,那么可能会导致数据破坏以及其他不该出现的结果。

当多个线程访问某个状态变量并且其中有一个线程执行写入操作时,必须采用同步机制来协同这些线程对变量的访问。Java中的主要同步机制是关键字synchronized,它提供了一种独占的加锁方式,但“同步”这个术语还包括volatile类型的变量,显式锁(Explicit Lock)以及原子变量。

同步和异步的概念:

同步:多个线程访问但是只有一个大门,虽然是多线程最终需要统一进入一个房间仍然需要排队。

异步:进入同一个房间但是每一个线程都各自拥有一扇独有的门。

多线程解决可变的状态(属性)出现非预想的结果的解决办法主要有三个:

  1. 不在多线程中进行对象共享。
  2. 让可变的状态修改为不可变的
  3. 使用上锁关键字让多线程改为同步。

线程安全的类可能是安全的,但是最终组合起来就不一定是安全的了。

第一部分 第2章:2.0:线程安全性

 

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值