`
臻是二哥
  • 浏览: 187885 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
博客专栏
Group-logo
Java技术分享
浏览量:0
社区版块
存档分类
最新评论

JAVA并发-并发编程概述

阅读更多
不知道各位童鞋是否干过在程序主进程中嵌入IO操作这样“任性”的事情,笔者曾经干过,而且那时候还觉得自己很棒。没办法,那时候还年轻啊。后来随着学习的深入,知道了有nio这种神一样的东西。但如果有其他方案,至少笔者是不会使用nio这个类的。毕竟程序的易读性还是很重要滴。多数时候,我们完全可以使用多线程和IO阻塞来代替非阻塞IO。
最近读了下经典《Java并发编程实践》,大师的书的确很棒,好了不说废话了,来写下我的笔记吧。
并发编程主要需要解决安全性,活跃性和性能的问题。下面是个人的理解:
1 安全性:程序可以确定的按照我们希望的时序执行。
2 活跃性:程序最终会输出正确的结果
3 性能:程序多长时间能输出正确的结果。
对于程序设计人员,我们需要在上面的3点之间寻找一种平衡,一种在满足安全性基础之上的平衡。
首先,我觉得有一个问题需要解决,那就是什么时候使用并发编程:并发编程一定是在需要的时候使用,什么是需要的时候?比如有一天,你的leader和你说,系统太慢了,以至于用户都快跑光了(哈哈,有点夸张),这个时候你就需要考虑一下是否可以使用多线程来做点什么。如果你确实发现了代码中有太多可以用多线程提升的地方,那么,。just do it。否则,还是不要轻易改变了,毕竟“稳定压倒一切吗”。先保证稳定在考虑性能。
当决定使用多线程的时候,我们就需要考虑安全性,活跃性以及性能了。
所谓的安全性,就是要求我们能够编写线程安全的代码,他的核心在于处理那些可以被多个线程共享的可变的变量。就像我在黑体部分说的,需要考虑线程安全的情况,一定是有下列3个条件:
1 一个可以被多个线程访问的变量
2 这个变量是共享的
3 这个变量的值是可以改变的
但你的程序中出现了这3个情况的时候,那么要小心了,需要考虑线程安全问题了。说白了,就是对于这个共享变量的访问时候的同步问题。就是常见的“读-改-写”和“核对后执行”情况。
比如我写了一个类:
@UnThreadSafe
class MyThread extends Thread
{
private int count=0;
public void run(){
count++;
System.out.println("counter="+count);
}
}

在这个例子中,MyThread类的变量count是可以被多个线程访问的,是共享的,是可变的(瞧,满足3个条件),我们需要考虑线程安全问题了。这是一个典型的“读-改-写”的问题,理论上我当然希望每个线程都能一口气执行完count++这条语句,但事实常常不是这样,可能thread-1刚刚读取到count为0,CPU就调度给了thread-2,这个时候thread-2读取到的count也是0,很显然,程序没有按照我们希望的时序执行,我们说他是不安全的。
我们可以使用线面的方式来让他变成线程安全的.
@ThreadSafe
class MyThread extends Thread
{
private final AtomicLong count=new AtomicLong(0);
public void run(){
int tmp=count.incrementAndGet();
System.out.println("counter="+tmp);
}
}

但是有些时候,并不总是有这样的第三方的类可以给我们使用的。

可能我们写了一个类,来根据一个请求的1-9的阿拉伯数字返回对应的大写汉字
public class MyServlet implements Servlet
{
   public void service(ServletRequest req,ServletResponse res){
   int i=getNum(req);
   String str=getHanziByNum(i);
   responseHanzi(res,i);
}
}

尽管service方法被多个线程执行,但不存在安全性的问题(没有多个线程共享的变量);这个时候,如果为了提高性能,需要将上一次请求的数据存储起来,我们来看:
@UnThreadSafe
public class MyServlet implements Servlet
{
private int num;
private String str;
   public void service(ServletRequest req,ServletResponse res){
   int i=getNum(req);
if(i==num)
   responseHanzi(res,str);
else
   String str1=getHanziByNum(i);
   num=i;
   str=str1;
   responseHanzi(res,str1);
}
}

在上面的代码中,出现了多个线程可以访问可变的的共享变量num和str,这时候需要考虑线程安全的问题了。有个最简单的方案将他变为线程安全的:
@ThreadSafe
public class MyServlet implements Servlet
{
private int num;
private String str;
   public synchronized void service(ServletRequest req,ServletResponse res){
   int i=getNum(req);
if(i==num)
   responseHanzi(res,str);
else
   String str1=getHanziByNum(i);
   num=i;
   str=str1;
   responseHanzi(res,str1);
}
}

程序设计人员不去具体分析哪些代码是需要同步的,而是同步一个大的区域,讲所有共享变量圈在里面,当然这样做实现了线程安全。但是没有考虑性能的问题。假设getHanziByNum()是一个非常耗时间的操作,那么同步方法service的执行时间将会非常慢,而整个方法有事同步的,很可能我们的并发代码 运行的性能比串行的还要差(创建和销毁线程需要时间,尽管很短)。因此,我们需要一些更加细粒度的同步,而不是像上面的粗粒度的同步。
@ThreadSafe
public class MyServlet implements Servlet
{
private int num;
private String str;
   public void service(ServletRequest req,ServletResponse res){
   int i=getNum(req);
   String str1=null;
   synchronized(this){
       if(i==num)
         str1=str;
   }
   if(str1=null){
       str1=getHanziByNum(i); 
       synchronized(this){
         num=i;
         str=str1;
       }
   }
   responseHanzi(res,str1);

}
}


上面的类是线程安全的,显然他比之前一个在性能上会更有优势。所以在解决多线程安全性的问题上,关于同步的粒度的大小需要我们仔细的研究,力度大一点可能实现起来简单,但是性能不一定太好。粒度太小的话,可能实现起来难度大,容易出错,怎么做到合适,需要我们自己权衡。

这个时候,如果我还想保存命中的变量
@ThreadSafe
public class MyServlet implements Servlet
{
private int num;
private String str;
private int hits;
private int totalHits;
   public synchronized double getHitRadio{
       return hits/totalHits;
   }   

   public void service(ServletRequest req,ServletResponse res){
   int i=getNum(req);
   String str1=null;
   synchronized(this){
       totalHits++;
       if(i==num){
         str1=str;
         hits++;
       }
   }
   if(str1=null){
       str1=getHanziByNum(i); 
       synchronized(this){
         num=i;
         str=str1;
       }
   }
   responseHanzi(res,str1);

}
}

可以看到,所有共享变量出现的地方都被加了锁(即同步操作),只不过同步的力度不同罢了。
综上所述,关于并发,我们的思路大概是这样的:
1 是否使用并发
2 如果使用用并发,哪些共享变量需要考虑安全性
3 对于需要考虑安全性的那些共享变量,要记得为每一个加锁
4 加锁的粒度粗细的权衡

0
3
分享到:
评论

相关推荐

    java高级技术JUC高并发编程教程2021(1.5G)

    java高级技术JUC高并发编程教程2021(1.5G) 〖课程介绍〗: java高级技术JUC高并发编程教程2021(1.5G) 〖课程目录〗:   01-JUC高并发编程-课程介绍.mp4 02-JUC高并发编程-JUC概述和进程线程概念(1).mp4 03-JUC...

    java并发编程实战(英文版)

    ### Java并发编程实战知识点概述 #### 一、Java并发特性详解 在《Java并发编程实战》这本书中,作者深入浅出地介绍了Java 5.0和Java 6中新增的并发特性。这些特性旨在帮助开发者更高效、安全地编写多线程程序。书中...

    Java 并发核心编程

    #### 一、Java并发概述 自Java诞生之初,其设计者就赋予了该语言强大的并发处理能力。Java语言内置了对线程和锁的支持,这使得开发者能够轻松地编写多线程应用程序。本文旨在帮助Java开发者深入理解并发的核心概念...

    Java并发编程-并发编程知识点总结.docx

    ### Java并发编程知识点总结 #### 1. 什么是线程? 线程是操作系统能够进行运算调度的最小单位,它被包含在进程之中,是进程中的实际运作单位。程序员可以通过线程进行多处理器编程,利用多线程对运算密集型任务...

    Java并发编程实践-电子书1-9章pdf

    《Java并发编程实践》是Java开发者深入理解并发编程的重要参考资料,尤其对于想要提升多线程应用设计和性能优化技能的程序员来说,这本书提供了丰富的实践经验和深入的理论知识。以下是根据提供的章节内容概述的一些...

    [Java并发编程实践].(Java.Concurrency.in.Practice).Brian.Goetz.英文原版.pdf

    ### Java并发编程实践 #### 书籍概述 《Java并发编程实践》是一本由Brian Goetz等人编写的关于Java并发编程的经典著作。本书深入浅出地介绍了Java 5.0及之后版本中新增加的并发特性,并对并发编程进行了全面而详尽...

    Java并发编程:设计原则与模式(第二版)-3

    4. **并发集合框架**:Java并发集合框架(java.util.concurrent包)提供了线程安全的数据结构,如ConcurrentHashMap、CopyOnWriteArrayList、ConcurrentLinkedQueue等,它们在多线程环境下表现优秀,避免了传统的...

    java并发编程实践(第一版)

    ### 并发编程概述 并发编程是指在同一个应用程序中,让不同的代码段能够同时执行,以提高程序执行效率。在多核处理器普及的今天,合理利用多线程可以大幅提高程序的性能和响应速度。Java作为一种支持并发的编程语言...

    Java并发编程与高并发解决方案-学习笔记

    ### Java并发编程与高并发...以上内容概述了Java并发编程的基础知识,包括并发与高并发的概念、CPU缓存及其一致性原理、以及Java内存模型的核心要素。这些基础知识对于理解Java并发编程的关键概念和技术具有重要意义。

    Java虚拟机并发编程.pdf

    由于您提供的文件信息中并没有...请注意,以上内容仅为基于您给出的标题和描述生成的知识点概述,实际的Java虚拟机并发编程书籍内容可能会更加详细和深入。如果您需要获取具体书籍内容的知识点,请提供相应的书籍内容。

    JAVA并发编程实践

    ### JAVA并发编程实践知识点概述 #### 一、Java并发编程基础 - **并发与并行的概念**:在Java并发编程中,“并发”是指程序中多个线程交替执行的现象,而“并行”则是指多个处理器同时执行多个任务的能力。理解这两...

    java并发编程基础PPT以及DEMO示例&操作系统概述PPT

    在本资源中,我们有两个主要的学习材料:一个关于“Java并发编程基础”的PPT和一个包含DEMO示例,另一个是“操作系统概述”的PPT。这些资料对于理解Java多线程编程以及操作系统的基础原理至关重要。 首先,让我们...

    java并发编程-AQS和JUC实战

    ### Java并发编程-AQS和JUC实战 #### 一、ReentrantLock 重入锁 **1.1 概述** - **基本介绍**: `ReentrantLock` 是一个实现了 `Lock` 接口的可重入互斥锁,提供比 `synchronized` 更丰富的功能。与 `synchronized...

    java并发实战中文文档

    标签“Java 并发编程 高清 有目录”准确地概述了文档的主要内容和特点。 Java并发编程是现代Java应用程序设计的关键组成部分,尤其在多核处理器和分布式系统中,合理地利用并发能够显著提高程序的性能和响应速度。...

    龙果学院java并发编程完整视频

    ### Java并发编程概述 Java并发编程是Java语言中的一个高级特性,它允许程序在多线程环境中运行,从而有效地利用多核处理器的能力,提高程序的执行效率。并发编程涉及到线程管理、同步机制、共享资源访问控制等多个...

    java并发编程实践 pdf

    ### Java并发编程概述 Java并发编程是Java平台的一个重要组成部分,它允许开发者创建能够同时执行多个任务的应用程序。通过合理地利用多核处理器的能力,提高程序的运行效率,Java并发编程为开发者提供了强大的工具...

Global site tag (gtag.js) - Google Analytics