Java并发编程
文章平均质量分 83
兰亭风雨
在路上
展开
-
【Java并发编程】之十七:深入Java内存模型—内存操作规则总结
主内存与工作内存 Java内存模型的主要目标是定义程序中各个变量的访问规则,即在虚拟机中将变量存储到内存和从内存中取出变量这样的底层细节。此处的变量主要是指共享变量,存在竞争问题的变量。Java内存模型规定所有的变量都存储在主内存中,而每条线程还有自己的工作内存,线程的工作内存中保存了该线程使用到的变量的主内存副本拷贝,线程对变量的所有操作(读取、赋值等)都必须在工作内存中进行,而不能直接读写主内存中的变量(根据Java虚拟机规范的规定,volatile变量依然有共享内存的拷贝,但是由于它特殊的操原创 2013-12-17 19:01:49 · 11287 阅读 · 2 评论 -
【Java并发编程】之五:volatile变量修饰符—意料之外的问题(含代码)
在JDK1.2之前,Java的内存模型实现总是从主存(即共享内存)读取变量,是不需要进行特别的注意的。而随着JVM的成熟和优化,现在在多线程环境下volatile关键字的使用变得非常重要。在当前的Java内存模型下,线程可以把变量保存在本地内存(比如机器的寄存器)中,而不是直接在主存中进行读写。这就可能造成一个线程在主存中修改了一个变量的值,而另外一个线程还继续使用它在寄存器中的变量值的拷贝,造成数据的不一致。要解决这个问题,就需要把变量声明为volatile(不稳定的),这就指示JVM,这个变量是不稳原创 2013-12-06 08:29:23 · 27228 阅读 · 10 评论 -
【Java并发编程】之十二:线程间通信中notifyAll造成的早期通知问题(含代码)
如果线程在等待时接到通知,但线程等待的条件还不满足,此时,线程接到的就是早期通知,如果条件满足的时间很短,但很快又改变了,而变得不再满足,这时也将发生早期通知。这种现象听起来很奇怪,下面通过一个示例程序来说明问题。 很简单,两个线程等待删除List中的元素,同时另外一个线程正要向其中添加项目。代码如下:原创 2013-12-11 08:48:39 · 8806 阅读 · 12 评论 -
【Java并发编程】之三:线程挂起、恢复与终止的正确方法(含代码)
转载请注明出处: Thread 的API中包含两个被淘汰的方法,它们用于临时挂起和重启某个线程,这些方法已经被淘汰,因为它们是不安全的,不稳定的。如果在不合适的时候挂起线程(比如,锁定共享资源时),此时便可能会发生死锁条件,另外,在长时间计算期间挂起线程也可能导致问题。 下面的代码演示了通过休眠来延缓运行,模拟长时间运行的情况,使线程更可能在不适当的时候被挂起:pu原创 2013-12-04 08:12:30 · 26618 阅读 · 7 评论 -
【Java并发编程】之二十三:并发新特性—信号量Semaphore(含代码)
在操作系统中,信号量是个很重要的概念,它在控制进程间的协作方面有着非常重要的作用,通过对信号量的不同操作,可以分别实现进程间的互斥与同步。当然它也可以用于多线程的控制,我们完全可以通过使用信号量来自定义实现类似Java中的synchronized、wait、notify机制。 Java并发包中的信号量Semaphore实际上是一个功能完毕的计数信号量,从概念上讲,它维护了一个许可集合,对控制一定资源的消费与回收有着很重要的意义。Semaphore可以控制某个资源被同时访问的任务数,它通过acquir原创 2013-12-25 08:11:25 · 13158 阅读 · 5 评论 -
【Java并发编程】之二十一:并发新特性—阻塞队列和阻塞栈(含代码)
阻塞队列是Java 5并发新特性中的内容,阻塞队列的接口是java.util.concurrent.BlockingQueue,它有多个实现类:ArrayBlockingQueue、DelayQueue、LinkedBlockingQueue、PriorityBlockingQueue、SynchronousQueue等,用法大同小异,这里简单举例看下ArrayBlockingQueue,它实现了一个有界队列,当队列满时,便会阻塞等待,直到有元素出队,后续的元素才可以被加入队列。 阻塞栈与阻塞队列相原创 2013-12-24 14:15:07 · 10279 阅读 · 4 评论 -
【Java并发编程】之二十二:并发新特性—障碍器CyclicBarrier(含代码)
CyclicBarrier(又叫障碍器)同样是Java 5中加入的新特性,使用时需要导入java.util.concurrent.CylicBarrier。它适用于这样一种情况:你希望创建一组任务,它们并发地执行工作,另外的一个任务在这一组任务并发执行结束前一直阻塞等待,直到该组任务全部执行结束,这个任务才得以执行。这非常像CountDownLatch,只是CountDownLatch是只触发一次的事件,而CyclicBarrier可以多次重用。原创 2013-12-25 00:05:51 · 8402 阅读 · 3 评论 -
【Java并发编程】之十八:第五篇中volatile意外问题的正确分析解答(含代码)
在《Java并发编程学习笔记之五:volatile变量修饰符—意料之外的问题》一文中遗留了一个问题,就是volatile只修饰了missedIt变量,而没修饰value变量,但是在线程读取value的值的时候,也读到的是最新的数据。但是在网上查了很多资料都无果,看来很多人对volatile的规则并不是太清晰,或者说只停留在很表面的层次,一知半解。 这两天看《深入Java虚拟机——JVM高级特性与最佳实践》第12章:Java内存模型与线程,并在网上查阅了Java内存模型相关资料,学到了不少东西,尤其在原创 2013-12-18 08:35:48 · 11925 阅读 · 13 评论 -
【Java并发编程】之二:线程中断(含代码)
转载请注明出处:使用interrupt()中断线程 当一个线程运行时,另一个线程可以调用对应的Thread对象的interrupt()方法来中断它,该方法只是在目标线程中设置一个标志,表示它已经被中断,并立即返回。 下面一段代码演示了休眠线程的中断public class SleepInterrupt extends Object implements Runnab原创 2013-12-03 16:08:06 · 27442 阅读 · 13 评论 -
【Java并发编程】并发编程大合集
转载请注明出处:http://blog.csdn.net/ns_code/article/details/17539599 为了方便各位网友学习以及方便自己复习之用,将Java并发编程系列内容系列内容按照由浅入深的学习顺序总结如下,点击相应的标题即可跳转到对应的文章 【Java并发编程】实现多线程的两种方法 【Java并发编程】线程的中断原创 2013-12-27 08:38:09 · 50939 阅读 · 14 评论 -
【Java并发编程】之一:可重入内置锁
每个Java对象都可以用做一个实现同步的锁,这些锁被称为内置锁或监视器锁。线程在进入同步代码块之前会自动获取锁,并且在推出同步代码块时会自动释放锁。获得内置锁的唯一途径就是进入由这个锁保护的同步代码块或方法。 当某个线程请求一个由其他线程持有的锁时,发出请求的线程就会阻塞。然而,由于内置锁是可重入的,因此如果摸个线程试图获得一个已经由它自己持有的锁,那么这个请求就会成功。“重入”意味着获原创 2013-11-28 23:32:13 · 21845 阅读 · 16 评论 -
【Java并发编程】之六:Runnable和Thread实现多线程的区别(含代码)
Java中实现多线程有两种方法:继承Thread类、实现Runnable接口,在程序开发中只要是多线程,肯定永远以实现Runnable接口为主,因为实现Runnable接口相比继承Thread类有如下优势: 1、可以避免由于Java的单继承特性而带来的局限; 2、增强程序的健壮性,代码能够被多个线程共享,代码与数据是独立的; 3、适合多个相同程序代码的线程区处理同一资源的情况。 下面以典型的买票程序(基本都是以这个为例子)为例,来说明二者的区别。原创 2013-12-06 10:15:33 · 58224 阅读 · 33 评论 -
【Java并发编程】之十三:生产者—消费者模型(含代码)
生产者消费者问题是线程模型中的经典问题:生产者和消费者在同一时间段内共用同一存储空间,生产者向空间里生产数据,而消费者取走数据。 这里实现如下的生产--消费模型: 生产者不断交替地生产两组数据“姓名--1 --> 内容--1”,“姓名--2 --> 内容--2”,消费者不断交替地取得这两组数据,这里的“姓名--1 ”和“姓名--2 ”模拟为数据的名称,“内容--1 ”和“内容--2 ”模拟为数据的内容。 由于本程序中牵扯到线程运行的不确定性,因此可能会出现以下问题:原创 2013-12-12 08:09:06 · 25941 阅读 · 6 评论 -
【Java并发编程】之十:使用wait/notify/notifyAll实现线程间通信的几点重要说明
在Java中,可以通过配合调用Object对象的wait()方法和notify()方法或notifyAll()方法来实现线程间的通信。在线程中调用wait()方法,将阻塞等待其他线程的通知(其他线程调用notify()方法或notifyAll()方法),在线程中调用notify()方法或notifyAll()方法,将通知其他线程从wait()方法处返回。 Object是所有类的超类,它有5个方法组成了等待/通知机制的核心:notify()、notifyAll()、wait()、wait(原创 2013-12-09 22:09:26 · 28223 阅读 · 21 评论 -
【Java并发编程】之七:使用synchronized获取互斥锁的几点说明
在并发编程中,多线程同时并发访问的资源叫做临界资源,当多个线程同时访问对象并要求操作相同资源时,分割了原子操作就有可能出现数据的不一致或数据不完整的情况,为避免这种情况的发生,我们会采取同步机制,以确保在某一时刻,方法内只允许有一个线程。 采用synchronized修饰符实现的同步机制叫做互斥锁机制,它所获得的锁叫做互斥锁。每个对象都有一个monitor(锁标记),当线程拥有这个锁标记时才能访问这个资源,没有锁标记便进入锁池。任何一个对象系统都会为其创建一个互斥锁,这个锁是为了分配给线程的,防原创 2013-12-08 15:13:56 · 20366 阅读 · 2 评论 -
【Java并发编程】之四:守护线程与线程阻塞的四种情况
转载请注明出处: Java中有两类线程:User Thread(用户线程)、Daemon Thread(守护线程) 用户线程即运行在前台的线程,而守护线程是运行在后台的线程。 守护线程作用是为其他前台线程的运行提供便利服务,而且仅在普通、非守护线程仍然运行时才需要,比如垃圾回收线程就是一个守护线程。当VM检测仅剩一个守护线程,而用户线程都已经退出运行时原创 2013-12-05 21:28:08 · 17033 阅读 · 4 评论 -
【Java并发编程】之十四:图文讲述同步的另一个重要功能:内存可见性
加锁(synchronized同步)的功能不仅仅局限于互斥行为,同时还存在另外一个重要的方面:内存可见性。我们不仅希望防止某个线程正在使用对象状态而另一个线程在同时修改该状态,而且还希望确保当一个线程修改了对象状态后,其他线程能够看到该变化。而线程的同步恰恰也能够实现这一点。 内置锁可以用于确保某个线程以一种可预测的方式来查看另一个线程的执行结果。为了确保所有的线程都能看到共享变量的最新值,可以在所有执行读操作或写操作的线程上加上同一把锁。下图示例了同步的可见性保证。原创 2013-12-13 08:31:43 · 12049 阅读 · 6 评论 -
【Java并发编程】之九:死锁(含代码)
当线程需要同时持有多个锁时,有可能产生死锁。避免死锁是一件困难的事,遵循以下原则有助于规避死锁: 1、只在必要的最短时间内持有锁,考虑使用同步语句块代替整个同步方法; 2、尽量编写不在同一时刻需要持有多个锁的代码,如果不可避免,则确保线程持有第二个锁的时间尽量短暂; 3、创建和使用一个大锁来代替若干小锁,并把这个锁用于互斥,而不是用作单个对象的对象级别锁;原创 2013-12-09 09:19:23 · 17015 阅读 · 5 评论 -
【Java并发编程】之八:多线程环境中安全使用集合API(含代码)
在集合API中,最初设计的Vector和Hashtable是多线程安全的。例如:对于Vector来说,用来添加和删除元素的方法是同步的。如果只有一个线程与Vector的实例交互,那么,要求获取和释放对象锁便是一种浪费,另外在不必要的时候如果滥用同步化,也有可能会带来死锁。因此,对于更改集合内容的方法,没有一个是同步化的。集合本质上是非多线程安全的,当多个线程与集合交互时,为了使它多线程安全,必须采取额外的措施。 在Collections类 中有多个静态方法,它们可以获取通过同步方法封装非同步集合而原创 2013-12-09 08:17:33 · 19621 阅读 · 3 评论 -
【Java并发编程】之二十:并发新特性—Lock锁和条件变量(含代码)
本文详细讲述了显示Lock锁的各项机制:可中断锁、公平锁、读锁、写锁、条件变量实现线程间协作、await、signal、signalAll。 Java 5中引入了新的锁机制——java.util.concurrent.locks中的显式的互斥锁:Lock接口,它提供了比synchronized更加广泛的锁定操作。Lock接口有3个实现它的类:ReentrantLock、ReetrantReadWriteLock.ReadLock和ReetrantReadWriteLock.WriteLock,即重入锁原创 2013-12-24 08:23:27 · 20674 阅读 · 7 评论 -
【Java并发编程】之十五:并发编程中实现内存可见的两种方法比较:加锁和volatile变量
在http://blog.csdn.net/ns_code/article/details/17288243这篇博文中,讲述了通过同步实现内存可见性的方法,在http://blog.csdn.net/ns_code/article/details/17101369这篇博文中,讲述了通过volatile变量实现内存可见性的方法,这里比较下二者的区别。 1、volatile变量是一种稍弱的同步机制在访问volatile变量时不会执行加锁操作,因此也就不会使执行线程阻塞,因此volatile变量是一原创 2013-12-16 08:22:32 · 10061 阅读 · 6 评论 -
【Java并发编程】之十一:线程间通信中notify通知的遗漏(含代码)
notify通知的遗漏很容易理解,即threadA还没开始wait的时候,threadB已经notify了,这样,threadB通知是没有任何响应的,当threadB退出synchronized代码块后,threadA再开始wait,便会一直阻塞等待,直到被别的线程打断。原创 2013-12-10 08:10:36 · 9228 阅读 · 9 评论 -
【Java并发编程】之十九:并发新特性—Executor框架与线程池(含代码)
在Java 5之后,并发编程引入了一堆新的启动、调度和管理线程的API。Executor框架便是Java 5中引入的,其内部使用了线程池机制,它在java.util.cocurrent 包下,通过该框架来控制线程的启动、执行和关闭,可以简化并发编程的操作。因此,在Java 5之后,通过Executor来启动线程比使用Thread的start方法更好,除了更易管理,效率更好(用线程池实现,节约开销)外,还有关键的一点:有助于避免this逃逸问题——如果我们在构造器中启动一个线程,因为另一个任务可能会在构造器结原创 2013-12-23 08:17:07 · 73387 阅读 · 14 评论