随着多核时代的到来,JAVA类库提供了更多的并发方面的处理,这里结合《Effective Java》做个总结:
1. 区分线程操作是并发还是为了通讯,不仅仅是并发的情况需要同步。
JAVA 对于32位以下(依赖于硬件)可以表示的类型,也就是除了double和long的,都是可以通过原子操作完成的,但是当一个线程改变了这个变量时,并不立即在另外一个线程里可以看到,这依赖于线程的通讯。
看如下例子:
/**
* @description 如下这种写法,在我的虚拟机上可以正常停止,但是如果虚拟机做过优化,则不一定能正确结束
* @author job
* @date 2010-8-16 下午08:48:25
* @version 1.0
*/
public class StopThread {
public static Boolean stopRequest = Boolean.FALSE;
public static void main(String[] args) throws InterruptedException {
Thread backThread = new Thread(new Runnable() {
public void run() {
int i= 0;
long start = System.nanoTime();
while(!stopRequest){
System.out.println(i);
i++;
}
long totalTime = System.nanoTime()-start;
System.out.println("time:"+totalTime);
}
});
backThread.start();
TimeUnit.SECONDS.sleep(1);
stopRequest = true;
}
}
运行结果为 time:997494594
可以看到在我的虚拟机上可以正常的通讯,但是在有些虚拟机上会将循环代码优化为
if(!stopRequest){
while(true)
i++;
}
这个就叫活性失败。为什么主线程和子线程需要通讯呢,这个和JMM (JAVA的内存模型)有关,JAVA给不同的线程分配了不同的内存,叫工作内存,工作内存之间互相使不可见的,只能通过主存进行通讯。可以有如下两种方法来进行同步
2. synchronized 同步,这个是在不同线程之间通过 wait 和notify事件进行同步,效率不高。
class SyncStopThread {
public static Boolean stopRequest = false;
private static synchronized void requestStop(){
stopRequest= true;
}
private static synchronized boolean stopRequest(){
return stopRequest;
}
public static void main(String[] args) throws InterruptedException {
Thread backThread = new Thread(new Runnable() {
public void run() {
int i= 0;
long start = System.nanoTime();
while(!stopRequest()){
System.out.println(i);
i++;
}
long totalTime = System.nanoTime()-start;
System.out.println("time:"+totalTime);
}
});
backThread.start();
TimeUnit.SECONDS.sleep(1);
requestStop() ;
}
}
3. 使用volatile 进行不稳定变量的声明。
volatile的语义, 其实是告诉处理器, 不要将我放入工作内存, 请直接在主存操作我.因此, 当多核或多线程在访问该变量时, 都将直接操作主存, 这从本质上, 做到了变量共享.效率更高
class VolatileStopThread {
public static volatile Boolean stopRequest = false;
public static void main(String[] args) throws InterruptedException {
Thread backThread = new Thread(new Runnable() {
public void run() {
int i= 0;
long start = System.nanoTime();
while(!stopRequest){
System.out.println(i);
i++;
}
long totalTime = System.nanoTime()-start;
System.out.println("time:"+totalTime);
}
});
backThread.start();
TimeUnit.SECONDS.sleep(1);
stopRequest =true ;
}
}
注意:volatile 只对原子性的操作起作用,如果是序列号的增加 i++这种操作,是不能通过volatile 来避免并发问题的,两个线程有可能同时读到一个值,进行操作,然后获得了相同的序列号,这种就是 安全性失败。最好的方式是使用atomic的类库,这个下篇博客详细介绍。
4. 总结:对于线程之间共享变量,有几个原则可以借鉴
(1)尽量将可变变量保存在线程中
(2)线程安全通讯(安全发布)的几种方法:保存在静态域中,作为初始化的一部分;保存在volatile、final或者通过正常锁定的域中,也可以放到concurrentMap等并发集合中。
(3)基本上通过volatile 和 atomic 能够解决一般的并发问题。
(4)volatile 适用于仅仅需要通讯,不需要互相排斥操作的情况下:一般来说,子线程和主线程之间是需要通讯的,子线程和子线程对可变参数的处理都是要互相排斥的。
补充同事的一个关于volatile 和atomic的诠释:
volatile 只是将内容放入主存,也就是共享内存,而一般的如果不使用这个声明,那就是放入二级缓存,其它线程可能将这个变量已经更新到主存,就引起脏读,它不能解决 int 和long等占用两个字节的操作,说白了就是:volatile只保证线程同时对存储单元的可见性。但是不保证原子性。要实现原子性,就要使用AUTOMIC。它基于乐观锁,通过循环的方式来不断轮询看是不是有线程更新了这个值。
一般我们的场景都是IO密集型运算,所以才可以做一些并发编程的优化。要是CPU密集型的话,CPU一直很忙,那就没有优化余地了。AUTOMIC这个包也是基于这个考虑才使用乐观并发的方式的。
分享到:
相关推荐
《Java并发编程实战》是Java并发编程领域的一本经典著作,它深入浅出地介绍了如何在Java平台上进行高效的多线程编程。这本书的源码提供了丰富的示例,可以帮助读者更好地理解书中的理论知识并将其应用到实际项目中。...
综合来看,该书不仅适合于对Java并发编程感兴趣的初学者,同样也适合有经验的开发者,作为一本参考资料和实践指南,读者可以通过它来加深对Java并发特性的理解和应用。书中丰富的案例分析和代码示例将有助于读者更...
Java并发编程是Java开发中的重要领域,特别是在多核处理器和分布式系统中,高效地利用并发可以极大地提升程序的性能和响应速度。以下是对标题和描述中所提及的几个知识点的详细解释: 1. **线程与并发** - **线程*...
《Java并发编程实战》是一本深入探讨Java平台并发编程的权威指南。这本书旨在帮助开发者理解和掌握在Java环境中创建高效、可扩展且可靠的多线程应用程序的关键技术和实践。它涵盖了从基本概念到高级主题的广泛内容,...
锁机制是Java并发编程中的另一大主题,包括内置锁(互斥锁)和显式锁(如`ReentrantLock`)。内置锁是`synchronized`关键字提供的,而显式锁提供了更细粒度的控制和更丰富的功能。书中可能还会讨论读写锁(`...
JAVA并发编程艺术 高清pdf : 1.并发变成的挑战 2. java并发机制的底层实现原理 3. java 内存模型 4. java并发编程基础 5.java中的锁。。。。。。。
JAVA并发编程实践中文版 英文版 原书源码 带书签 java_concurrency_in_practice.pdf 英文版还是不错的,但是中文版的译者典型的没有技术功底,介绍上说什么专家, 翻译的非常差劲,有些句子都不通顺,都不知道自己去...
这份“java并发编程内部分享PPT”显然是一个深入探讨这一主题的资料,旨在帮助开发者理解并掌握Java并发编程的核心概念和技术。 在Java并发编程中,首先我们需要了解的基本概念是线程。线程是操作系统分配CPU时间的...
《Java并发编程实战》是一本深入探讨Java平台并发编程的权威指南,由Tim Peierls等人与Brian Goetz合著,旨在帮助Java开发者理解和掌握在多线程环境中编写高效、安全的代码。这本书由拥有丰富经验的JDK并发大师及...
综上所述,《Java并发编程实战》不仅涵盖了Java并发编程的基础知识和技术细节,还包含了丰富的实践经验和前瞻性的思考,是任何一位从事Java开发工作的程序员不可或缺的学习资源。无论是初学者还是有经验的开发者都能...
《Java并发编程实践》是一本深入探讨Java多线程编程的经典著作,由Brian Goetz、Tim Peierls、Joshua Bloch、Joseph Bowles和David Holmes等专家共同编写。这本书全面介绍了Java平台上的并发编程技术,是Java开发...
Java并发编程是软件开发中的一个关键领域,尤其是在大型企业级应用和分布式系统中。通过学习相关的书籍,开发者可以深入理解如何有效地设计和实现高效的多线程应用程序,避免并发问题,如竞态条件、死锁、活锁等。...
《Java并发编程的艺术》这本书是Java开发者深入理解并发编程的重要参考书籍。这本书全面地介绍了Java平台上的并发和多线程编程技术,旨在帮助开发者解决在实际工作中遇到的并发问题,提高程序的性能和可伸缩性。 ...
《JAVA并发编程艺术》是Java开发者深入理解和掌握并发编程的一本重要著作,它涵盖了Java并发领域的核心概念和技术。这本书详细阐述了如何在多线程环境下有效地编写高效、可靠的代码,对于提升Java程序员的技能水平...
Java并发编程实践是Java开发中不可或缺的一个领域,它涉及到如何高效、正确地处理多线程环境中的任务。这本书的读书笔记涵盖了多个关键知识点,旨在帮助读者深入理解Java并发编程的核心概念。 1. **线程和进程的...
总的来说,《JAVA并发编程实践》是一本深度和广度兼备的并发编程指南,无论是初学者还是有经验的Java开发者,都能从中受益匪浅。通过学习这本书,你将能够有效地应对并发编程中的挑战,提升你的多线程编程能力。
《Java并发编程从入门到精通》是一本专为Java开发者设计的深度学习并发编程的书籍。作者韩剑锋,凭借其12年的IT行业经验,曾担任多家IT公司的研发总监和技术总监,以其丰富的实战经验和深厚的理论知识,为读者提供了...
"Java并发编程与实践"文档深入剖析了这一主题,旨在帮助开发者理解和掌握如何在Java环境中有效地实现并发。 并发是指在单个执行单元(如CPU)中同时执行两个或更多任务的能力。在Java中,这主要通过线程来实现,...