总结并发编程

Posted muacheng

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了总结并发编程相关的知识,希望对你有一定的参考价值。

一.java内存模型

1.线程通信机制

1.共享内存(java使用)

共享内存这种方式比较常见,我们经常会设置一个共享变量。然后多个线程去操作同一个共享变量。从而达到线程通讯的目的。例如,我们使用多个线程去执行页面抓取任务,我们可以使用一个共享变量count来记录任务完成的数量。每当一个线程完成抓取任务,会在原来的count上执行加1操作。这样每个线程都可以通过获取这个count变量来获得当前任务的完成情况。当然必须要考虑的是共享变量的同步问题,这也共享内存容易出错的原因所在。
技术图片

2.消息传递

消息传递方式采取的是线程之间的直接通信,不同的线程之间通过显式的发送消息来达到交互目的。消息传递最有名的方式应该是actor模型了(erlang使用此模型)。在这种模型下,一切都是actor(类似于面向对象的oo),所有的actor之间的通信都必须通过传递消息才能达到。每个actor都有一个收件箱(消息队列,所以它是一个异步模型)用来保存收到其他actor传递来的消息
技术图片

2.内存模型

1.重排序

编译器和处理器可能会对操作做重排序。编译器和处理器在重排序时,会遵守数据依赖性,编译器和处理器不会改变存在数据依赖关系的两个操作的执行顺序
怎样判断两个操作存在依赖关系?
如果两个操作访问同一个变量,且这两个操作中有一个为写操作,此时这两个操作之间就存在数据依赖性

名称 代码示例 说明
写后读 a = 1;b = a; 写一个变量之后,再读这个位置
写后写 a = 1;a = 2; 写一个变量之后,再写这个变量
读后写 a = b;b = 1; 读一个变量之后,再写这个变量

上面三种情况,只要重排序两个操作的执行顺序,程序的执行结果将会被改变。

2.as-if-serial

as-if-serial 语义的意思指:不管怎么重排序(编译器和处理器为了提高并行度),(单线程)程序的执行结果不能被改变。编译器,和处理器都必须遵守 as-if-serial 语义

3.happens-before

在并发环境下,指令重排序可能出现问题,为了避免编译优化对并发编程安全性的影响,需要happens-before规则定义一些禁止编译优化的场景,保证并发编程的正确性

public class VolatileExample {
    int x = 0 ;
    volatile boolean v = false;
    public void writer(){
        x = 42;
        v = true;
    }

    public void reader(){
        if (v == true){
            // 这里x会是多少呢
        }
    }
}

jdk1.5之前,线程B读到的变量x的值可能是0,也可能是42,jdk1.5之后,变量x的值就是42了。原因是jdk1.5中,对volatile的语义进行了增强.来看一下happens-before规则在这段代码中的体现。

1.规则1:程序顺序性规则
一个线程中,按照程序的顺序,前面的操作happens-before后续的任何操作(对于这一点,可能会有疑问。顺序性是指,我们可以按照顺序推演程序的执行结果,但是编译器未必一定会按照这个顺序编译,但是编译器保证结果一定==顺序推演的结果)
2.规则二:volatile规则
对一个volatile变量的写操作,happens-before后续对这个变量的读操作
3.规则三:传递性规则
如果A happens-before B,B happens-before C,那么A happens-before C
jdk1.5的增强就体现在这里。回到上面例子中,线程A中,根据规则一,对变量x的写操作是happens-before对变量v的写操作的,根据规则二,对变量v的写操作是happens-before对变量v的读操作的,最后根据规则三,也就是说,线程A对变量x的写操作,一定happens-before线程B对v的读操作,那么线程B在注释处读到的变量x的值,一定是42
4.规则四:管程中的锁规则
对一个锁的解锁操作,happens-before后续对这个锁的加锁操作
5.规则五:线程start()规则
主线程A启动线程B,线程B中可以看到主线程启动B之前的操作。也就是start() happens before 线程B中的操作
6.规则六:线程join()规则
主线程A等待子线程B完成,当子线程B执行完毕后,主线程A可以看到线程B的所有操作。也就是说,子线程B中的任意操作,happens-before join()的返回

















以上是关于总结并发编程的主要内容,如果未能解决你的问题,请参考以下文章

golang代码片段(摘抄)

并发编程:我对Java并发编程的总结和思考

并发编程总结

线程学习知识点总结

关于Java并发编程的总结和思考

并发编程 - 总结