您的位置:首页 > 编程语言 > Java开发

【Java并发】JAVA并发编程实战-读书笔记1

2016-10-11 21:14 239 查看
    从今天开始阅读《JAVA并发编程实战》这本书,并记录下自己阅读的记录。

    首先感谢该书的原作者,几个外国的大神,也感谢韩锴、方妙两位译者。

    程序在各自的进程中运行,相互分离,各自独立执行。由操作系统分配空间。

    进程会通过一些原始的机制相互通信:Socket、信号处理、共享内存、信号量和文件。

    线程有时被称为轻量级的进程。

    同一个进程中的线程访问相同的变量,并从同一个堆中分配对象,但是如果没有机制来同步管理共享数据,就会出现一个线程修改另一个线程正在使用的数据,从而产生意外的结果。

    在没有同步的情况下,多线程的各个操作的顺序是不可预测的。

private int value;

public int getNext(){

return value++;
}
    上面的方法在单线程时没有问题,如果出现了下面的执行情况。
        1,线程A:获得了value,为0。

        2,线程B:获得了value,为0。

        3,线程A:执行了++,value为1。

        4,线程B:执行了++,value为1。

        5,线程A:得到了value为1。

        6,线程B:得到了value为1。

    正确的情况下,线程B获得的value应该是2。但是由于多线程的介入,指令执行的顺序不定,导致了错误的发生。

    这里的问题在于,value++看似是一个语句,其实是分为三个步骤执行的,首先获得value的值,然后执行加1的操作,最后写回到value上。

    这就是常见的并发危险:竞争条件(race condition)。当被多线程访问时,上面的方法能否返回不同的值,取决于CPU调度的顺序,这是我们不希望看到的。

    允许多线程访问和修改相同的
b508
变量,给顺序编程模型引入了一些非顺序的因素。

    简单的处理方法是,使用synchronized来修饰上面的方法,保证访问的唯一性。

    在不使用同步的时候,编译器、硬件和运行时事实上对时间和活动的顺序是很随意的。

    如果安全意味着什么坏事都没有发生过,活跃度关注是好事最终发生了。当一个活动进入了某种它永远无法在继续执行的状态时,活跃度失败就发生了。顺序程序中,粗心造成的死循环就是一种活跃度失败。

   通过框架来访问应用程序中的组件,组件需要访问程序的状态,因此要求在所有的代码路径上,必须是线程安全的。

    Timer用来调度一些稍后运行的任务,TimerTasks运行在由Timer管理的线程中,如果TimerTasks访问了其他应用程序正在访问的数据,那么不仅TimerTask需要线程安全,并且那些被同时访问的数据也要相应的保护措施。

    编写线程安全的代码,本质上就是管理对状态的访问,而且通常是共享的、可变的状态。

    所谓共享就是一个变量可以被多个线程访问,所谓可变就是变量的值在他的生命周期内是可以改变的。所以我们要在不可控制的并发中保护数据的安全性。

    Java的首要同步机制就是synchronized关键字,他提供了独占锁。

    如果多个线程访问同一个变量,有3种方法修复

        1,不要跨线程共享变量。

        2,使得状态变量为不可变。

        3,在任何访问状态变量的时候使用同步。

    一开始将一个类设计成线程安全的,比后期重新修复他更容易。

    设计线程安全的类时,优秀的面向对象技术——封装、不可变性以及明确的不变约束——会给你提供诸多的帮助。

    首先让你的代码正确,然后在让他跑的更快,总是一个良好的实践。

    一个线程安全程序是完全由线程安全类构成的吗?不必要——完全由线程安全类构成的程序也未必是线程安全的。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: