【Java程序性能优化 第一版】第四章(并发控制方法)

10 篇文章 0 订阅
9 篇文章 0 订阅

                                       4.4 并发控制方法

    并行程序开发将不可避免地要涉及多线程,多任务间的协作和数据共享等问题。在JDK中,提供了多种途径实现多线程间的并发控制。常用的方法有:内部锁,重入锁,读写锁,信号量等

    4.4.1 Java内存模型与volatie

    在Java中,每一个线程有一块工作内存区,其中存放着被所有线程共享的主内存中的变量的值的拷贝。当线程执行时,它在自己的工作内存中操作这些变量。为了存取一个共享的变量,一个线程通常先获取锁定并且清除它的工作内存区,这保证该共享变量从所有线程的共享内存区正确地装入到线程的工作内存区,当线程解锁时保证该工作内存区中变量的值写回到共享内存中。  

    一个线程可以执行的操作有使用(usd),赋值(assign),装载(load),存储(store),锁定(lock),解锁(unlock)。而主内存可以执行的操作有读(read),写(write),锁(lock),解锁(unlock)。每一个操作都是原子的。

   当一个线程使用一个变量时,不论程序是否正确地使用线程的同步操作,它获取的值一定是由它本身或者其它线程存储到变量中的值。例如,如果两个线程把不同的值或者对象引用存储到同一个共享变量中,那么该变量中的值要么是这个线程的,要么是那个线程的,共享变量的值不会由两个线程的引用值组合而成(除long,double外)。

   一个变量是Java程序可以存取的一个地址,它不仅包括基本类型变量,引用类型变量,而且还包括数组类型变量。保存在主内存区的变量可以被所有线程共享,但一个线程存取另一个线程的参数或局部变量是不可能的,所以开发人员不必担心局部变量的线程安全问题

   使用,赋值,锁定,解锁操作都是线程的执行引擎和线程的工作内存的原子操作;但主内存和线程的工作内存间的数据传送并不是满足原子性,即当数据从主内存复制到工作内存时,必须出现两个动作:第一,由主内存执行的读(read)操作;第二,由工作内存执行的相应的load操作。当数据从工作内存拷贝到主内存时,也出现两个操作:第一个,由工作内存执行的存储(store)操作;第二,由主内存执行的相应的写(write)操作。由于主内存和工作内存间传送数据需要一定的时间。而且每次所消耗的时间可能是不同的。比如,某一线程内的代码是先给变量a赋值,再给变量b赋值,在另一个线程中,可能先在主内存中看见变量b的更新,再看见变量a的更新。当然,在一个线程中对同一个变量的操作次序,一定和该线程中的实际次序相吻合。

   各个操作的含义如下

 □线程的use操作把一个变量在线程工作内存中的拷贝内容传送给线程执行引擎。

 □线程的assign操作把一个值从线程执行引起传送到变量的线程工作内存。

 □主内存的read操作把一个变量的主内存拷贝的内容传输到线程的工作内存,以便load操作使用。

 □线程的load操作把read操作从主内存中得到的值放入变量的线程工作内存中。

 □线程的store操作把一个变量的线程工作内存拷贝内容传送到主内存中,以便write操作使用。

 □主内存的write操作把store操作从线程工作内存中得到的值放入主内存中的变量拷贝中。

 □ 主内存的lock操作使线程获得一个独占锁。

 □ 主内存的unlock操作使线程释放一个独占锁。

    这样,线程和变量的相互作用由use,assign,load和store操作的序列组成。主内存为每个load操作执行read操作,为每个store操作执行write操作。线程锁定和解锁由lock和unlock操作完成。

     线程的每个load操作有唯一一个主内存的read操作和它相匹配,这个load操作跟在read操作的后面;线程的每个store操作有唯一一个主内存的write操作和它相匹配,这个write操作跟在store操作的后面

     double和long类型变量的非原子处理:如果一个doble或者long变量没有声明为volatile,则变量在进行read或write操作时,主内存把它当做两个32位的read或write操作进行处理,这两个操作在时间上是分开的,可能会有其它操作介于它们之间。如果这种情况发生,则两个并发的线程对共享的非volatile类型的double和long变量赋不同的值,那么随后对该变量的使用而获取的值可能不等于任何一个线程所赋的值,而可能是依赖于具体应用的两个线程所赋的值的混合。因此,在32位的系统中,必须对double或long进行同步。

   由于每个线程都有自己的工作内存区,因此当一个线程改变自己的工作内存中的数据时,对其它线程来说,可能是不可见的。为此,可以使用volatile关键字迫使所有线程均读写主内存中的对应变量,从而使得volatile变量在多线程间可见

   声明为volatile的变量可以做以下保证:

   (1)其它线程对变量的修改,可以即时反应在当前线程中。

   (2)确保当前线程对volatile变量的修改,能即时写回共享主内存中,并被其它线程所见。

   (3)使用volatile声明的变量,编译器会保证其有序性。

至此,我对文章的理解能力已经跟不上(之前用到线程很少),所以我在找其它的相关书籍进行阅读和笔记,需要阅读本章的可以去看看别人的博客,如果读者和我一样这里不懂得话,可以按照我的接下来的笔记进行阅读,确保循序渐进

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值