`

Java并发编程基础

阅读更多

 

 

 

Java 并发编程基础

1. 线程 的风险

1.1 安全风险

线程不安全:

Public class UnsafeSequence{

      Private int value;

      Public int getNext(){

  Return value++;

}

}

 


线程安全:

Public class UnsafeSequence{

      Private int value;

      Public synchronized int getNext(){

  Return value++;

}

}

 


1.2 活跃度 (liveness) 风险

当一个活动进入某种永远它无法再继续执行的状态时, liveness failure 就发生了。例如死锁 (deadlock) 、饥饿 (starvation) 和活锁 (livelock)


1.3 性能风险

性能问题涉及很多方面,包括服务时间、响应性、吞吐量、资源消费或者可伸缩性的不良表现。设计良好的应用程序中使用线程,能够获得纯粹的性能收益,但是线程仍然会给运行带来一定的开销:

上下文切换: 当调度程序临时挂起当前运行的线程时,另一个线程开始运行,这再多个线程组成的应用程序中是很频繁的,并且带来巨大的系统开销:

l  保存和恢复线程执行的上下文,离开执行现场,并且 CPU 时间会花费在对线程的调度而不是在运行上。

l  当线程共享数据的时候,他们必须使用同步机制,这个机制会限制编译器的优化

l  同步也能够清空或者锁定内存和高速缓存,并在共享内存的总线上创建同步通信

1.4 线程无处不在

线程实际上是无处不在的,即使你的程序没有使用多线程,然而你依赖的第三方或者你的程序所处的框架会为你创建线程。在你使用第三方包的时候,尤其要注意线程安全问题。

2. 线程安全

2.1 概览

编写线程安全的代码,本质上就是管理对状态的访问,而且通常都是共享的、可变的状态。 无论何时,只要有多于一个的线程访问给定的状态变量,而且其中某个线程会写入该变量,此时必须使用协调线程对变量的访问。

并发编程是保证正确性的前提下对性能的追求。

 

 

在没有正确使用同步的情况下,如果多个线程访问了同一个变量。你的程序就存在隐患。有 3 个方法可以修复它:

l  不要跨线程共享变量

l  使变量为不可变的

l  在任何访问状态变量的时候都使用同步

 

 

设计线程安全的类时,优秀的面向对象技术 --- 封装、不可变性以及明确的不变约束 会给你提供诸多的帮助。

2.2 什么是线程安全

非线程安全的实例:

 

Public class ImageServlet implements Servlet{

      Public String imageURL;

      Public void service(ServletRequest req, ServletResponse resp) {

    imageURL = req.getParameter(“imageURL”);

     

   out.println(imageURL);

}

}

 



 

分析: 由上面图可以看出, ThreadA ,写入新值后,在还没有写入 Client 之前, Thread B 又写入了新值,从而客户 A 上传图片,显示在页面上时,变成了客户 B 上传的图片。

 

 

改进:

Public class ImageServlet implements Servlet{

      Public void service(ServletRequest req, ServletResponse resp) {

  String imageURL = req.getParameter(“imageURL”);

     

   out.println(imageURL);

}

}

 

这样改进以后,就线程安全了,记住:

 

 

无状态的 Servlet (对象)永远是线程安全的。

 

 

2.3 原子性

由于不是原子性操作而造成的线程安全问题:

 

Public class UnsafeCount   implements Servlet{

      Public int count;

      Public void service(ServletRequest req, ServletResponse resp) {

    count++;

     

   out.println(imageURL);

}

}

 

2.3.1 竞争条件 check-then-act

线程安全问题的形成,通常有一定的竞争条件。检查再运行是典型的竞争条件:

Public class LazyInitRace {

      Private ExpensiveObject instance = null;

      Public ExpensiveObject getInstance(){

    If (instance == null)

           Instance = new ExpensiveObject();

   Return instance;

}

}

2.3.2 复合操作

刚才计数器的问题和 check-then-act 的问题的根本原因是这些操作并不是一步操作,专业术语称为原子操作:

 

假设有操作 A B ,如果从执行 A 的线程的角度看,当其他线程执行 B 时,要么 B 全部全部执行完成,要么一点都没有执行,这样 A B 互为原子操作。

 

对于上面说的计数器,我们可以如下改进:

Public class CountFactorizer   implements Servlet{

      Public final AtomicLong count = new AtomicLong(0);

      Public void service(ServletRequest req, ServletResponse resp) {

    Count.incrementAndGet();

     

   out.println(imageURL);

}

}

 

 

 

2.4

2.4.1 内部锁

Java 提供了原子性的内置锁机制: sychronized 块。它包含两个部分:锁对象的引用和这个锁保护的代码块:

synchronized(lock) {

// 访问或修改被锁保护的共享状态

}

内部锁扮演了互斥锁( mutual exclusion lock, 也称作 mutex )的角色,一个线程拥有锁的时候,别的线程阻塞等待。

2.4.2 重进入(Reentrancy

重入性:指的是同一个线程多次试图获取它所占有的锁,请求会成功。当释放锁的时候,直到重入次数清零,锁才释放完毕。

Public class Widget {

      Public synchronized void doSomething(){

          

}

}

Public class LoggingWidget extends Widget {

Public synchronized void doSomething(){

      System.out.println(toString()+”:calling doSomething”);

      Super.doSomething();

}

}

 

 

2.6 活跃度和性能

弱并发性:

 

Public class CountFactorizer   implements Servlet{

      Public int count = 0;

      Public synchronized void service(ServletRequest req, ServletResponse resp) {

      Count++;   

     

}

}

 

改进:

Public class CountFactorizer   implements Servlet{

      Public int count = 0;

      Public void service(ServletRequest req, ServletResponse resp) {

           Synchronized(this){

            Count++;   

}

     

}

}

 

并不是同步块越小越好,决定 synchronized 块大小的需要权衡各种设计要求,包括安全性、简单性和性能。有些耗时的计算或者操作,比如网络或控制台 I/O ,难以快速完成,执行这些操作期间不要占有锁。

 

  • 大小: 31.1 KB
  • 大小: 31.7 KB
  • 大小: 31.7 KB
  • 大小: 32.6 KB
分享到:
评论

相关推荐

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

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

    Java 并发编程实战.pdf

    ### Java并发编程基础 - **并发与并行**:并发是指多个任务在同一时间段内被执行(但不一定同一时刻),而并行则是指多个任务同时执行。理解这两者的区别对于深入学习并发编程至关重要。 - **Java并发机制**:Java...

    JAVA并发编程艺术 高清pdf

    JAVA并发编程艺术 高清pdf : 1.并发变成的挑战 2. java并发机制的底层实现原理 3. java 内存模型 4. java并发编程基础 5.java中的锁。。。。。。。

    JAVA并发编程实践 中文 高清 带书签 完整版 Doug Lea .pdf

    ### 一、Java并发编程基础 #### 1.1 并发与并行的概念 - **并发**:指多个事件在同一时间段内发生。 - **并行**:指多个事件在同一时刻发生。 在Java并发编程中,通常会涉及多个线程共享资源并同时运行的情况,...

    JAVA并发编程实践

    ### 一、Java并发编程基础 #### 1.1 并发与并行 - **并发**:指在同一时间段内处理多个任务的能力。 - **并行**:指同一时刻处理多个任务的能力。并行依赖于多处理器或多核处理器的支持。 #### 1.2 Java并发工具类...

    《java 并发编程实战高清PDF版》

    总之,《Java并发编程实战》是一本全面介绍Java并发编程的书籍,适合有一定Java基础并希望提升并发编程能力的开发者阅读。通过学习,你可以掌握解决并发问题的策略和技巧,编写出更加健壮和高效的多线程应用。

    java并发编程实践

    #### 一、Java并发编程基础 ##### 1.1 并发与并行概念区分 在Java并发编程实践中,首先需要理解“并发”与“并行”的区别。“并发”指的是多个任务同时进行,但实际上可能是在多线程环境下通过交替执行的方式实现的...

    JAVA并发编程实践.pdf

    ### Java并发编程基础 #### 1. 并发与并行 - **并发**:指的是多个任务在同一时间段内被执行(可能不是同一时刻)。 - **并行**:指的是多个任务在同一时刻被执行。 在Java中,并发主要是通过多线程来实现的,而...

    java并发编程内部分享PPT

    此外,Java并发编程还包括对并发容器的使用,如ArrayList、LinkedList、HashSet、HashMap等基础容器在并发环境下可能存在问题,Java提供了一些线程安全的容器,如Vector、HashTable以及java.util.concurrent包下的...

    Java并发编程实战华章专业开发者书库 (Tim Peierls 等 美Brian Goetz).pdf

    《Java并发编程实战》提供了深入浅出的指导,涵盖了从基础理论到高级技术的广泛内容。 第一部分介绍了并发编程的基础,包括线程安全性的概念,如何构建线程安全的类,以及Java平台提供的并发工具如线程、同步机制等...

    java并发编程书籍

    Java并发编程是软件开发中的一个关键领域,尤其是在大型企业级应用和分布式系统中。通过学习相关的书籍,开发者可以深入理解如何有效地设计和实现高效的多线程应用程序,避免并发问题,如竞态条件、死锁、活锁等。...

    JAVA并发编程实践.pdf+高清版+目录 书籍源码

    《JAVA并发编程实践》这本书是Java开发者深入理解并发编程的重要参考资料。它涵盖了Java并发的核心概念、工具和最佳实践,旨在帮助读者在多线程环境下编写高效、安全的代码。 并发编程是现代软件开发中的关键技能,...

    Java并发编程从入门到精通(pdf)(附源码)

    本书首先会介绍Java并发编程的基础概念,包括线程的创建与管理、同步机制如synchronized关键字和Lock接口,以及如何避免常见的并发问题,如死锁、活锁和饥饿。这些基础知识是理解并发编程的基石,通过深入浅出的讲解...

    Java并发编程实践.pdf

    #### 一、并发编程基础 ##### 1.1 并发与并行的区别 在Java并发编程中,首先需要理解“并发”(Concurrency)和“并行”(Parallelism)的区别。“并发”指的是多个任务在同一时间段内交替执行,而“并行”则指的是...

    java并发编程与实践

    "Java并发编程与实践"文档深入剖析了这一主题,旨在帮助开发者理解和掌握如何在Java环境中有效地实现并发。 并发是指在单个执行单元(如CPU)中同时执行两个或更多任务的能力。在Java中,这主要通过线程来实现,...

    java并发编程

    Java并发编程是Java开发者必须掌握的关键技能之一,它涉及到如何在多线程环境中高效、安全地执行程序。并发编程能够充分利用多核处理器的计算能力,提高应用程序的响应速度和整体性能。《Java编程并发实战》这本书是...

    Java并发编程设计原则和模式

    一、并发编程基础 并发是指两个或多个操作在同一时间段内执行,但并不意味着这些操作是并行的,即同时在不同处理器上执行。在Java中,主要通过线程实现并发,线程是操作系统调度的基本单位,每个线程都有自己的程序...

Global site tag (gtag.js) - Google Analytics