zoukankan      html  css  js  c++  java
  • 并发编程实战-第二章学习

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

    如果当多个线程访问同一个可变的状态变量时没有使用合适的同步,那么程序就会出现错误,有三种方式可以修复这个问题:

    • 不在线程之间共享该状态变量(有点扯,既然我要共享一个状态变量,怎么可能不共享,只能说不共享肯定不会涉及状态的同步)
    • 将状态变量修改为不可变的变量。
    • 在访问状态变量时使用同步

    什么是线程安全性

    线程安全性的核心是正确性,即当多个线程访问某个类时,这个类使用都能变现出正确的行为,那么这个类就是线程安全的。

    在线程安全性一章中给出的定义:

    当多个线程访问某个类时,不管运行环境采用何种调度凡是或者这些线程将如何交替执行,并且在主调代码中不需要任何额外的同步或协同,这个类都能变现出正确的行为,那么就称这个类时线程安全的

    无状态对象一定是线程安全的,无状态即不包括任何域、也不包括任何对其他类中的域的引用。

    原子性

    原子操作是指,对于访问同一个状态的所有操作(包括该操作本身)来说,这个操作是一个原子的操作。(个人理解:所谓的原子,即最小单位,不可再分割,对于操作来说,及时是复合操作,同样通过加锁等其他方式将其捆绑在一起完成)

    该节提出了产生数据不一致的问题,从而引出了,“先检查后执行”的操作,即通过一个可能失效的观察结果来决定下一步的动作。通过举例了两个朋友相约咖啡厅的故事进行了描述,通俗易懂,其中我个人认为比较重要的一句----“当你迈出前门时,你在星巴克A的观察结果将变得无效,因为他可能已经从后门进入了星巴克,只是你不知道而已”。、

    通过long的couut操作说明了符合操作,++count,涉及的操作为读取-修改-写入三部分操作,通过使用java.util.concurrent.atmoic包中的原子变量类AtomicLong来代替long类型来解决该问题是其成为一个线程安全的操作。

    在实际情况中,应尽可能地使用现有的线程安全对象(例如AtomicLong)来管理类的状态,与非线程安全的对象相比,判断线程安全对象的可能状态及其状态转换情况要更为容器,
    从而更容易维护和验证线程安全性

     加锁机制

    要保值状态的一致性,就需要在单个原子操作中更新所有相关的状态变量。

    重入意味着获取锁的操作的粒度是线程,而不是调用。重入的一种实现方法是,为每个锁关联一个获取计数值和一个所有者线程。

     一种常见的加锁约定是,将所有的可变状态都封装在对象内部,并通过对象的内置锁对所有访问可变的代码路径进行同步,使得在该对象上不会发生并发访问。

    需要注意的一点是即使是同步方法的符合操作,同样会导致竞态条件问题。如下代码,虽然vector是的每个方法是原子方法,但是复合操作,同样会导致出现数据不一致问题。

    1 if ( !vector.contains(element))
    2     vector.add(element)

    遗留问题

    1、原子性小节同样提到了单例的实现,该问题需要统一整理所有单例的实现方法,记一个遗留问题,下周解决

    已经复习了单例的相关知识,见:http://www.cnblogs.com/woniu4/p/8287484.html

  • 相关阅读:
    senlin __init__() got an unexpected keyword argument 'additional_headers'
    Delphi 全局画点TCanvas.Pixels[X,Y]
    sql server 列修改null 变成not null
    Delphi记录record中的变体
    delphi无边框可拖动窗体
    bootstrap相关资料
    重装windows导致grub损坏
    RabbitMQ的安装(Docker安装)
    RabbitMQ的安装以及使用(Windows环境)
    如果安装rabittmq后,输入http://localhost:15672不出页面的
  • 原文地址:https://www.cnblogs.com/woniu4/p/8284244.html
Copyright © 2011-2022 走看看