`

Java 并发编程基础-共享对象

阅读更多

 

Java 并发编程基础 - 共享对象

 

目录

Java 并发编程基础 - 共享对象 ... 1

1.            可见性 ... 1

1.1过期数据 ... 2

1.2 非原子的 64位操作 ... 3

1.3 Volatile变量是有代价的 ... 3

2.            发布和逸出 ... 3

3.            线程封闭 ... 5

3.1      栈限制 ... 5

3.2      ThreadLocal 5

3.3      不可变性 ... 6

 

1. 可见性

在没有同步的情况下,编译器,处理器,运行时安排操作的执行顺序可能完全出人意料,在没有进行适当同步的多线程程序中,尝试推断哪些“必要”发生在内存中的动作是,你总是会判断错误。

Public class NoVisibility{

      Private static boolean ready;

      Private static int number;

      Private static class ReaderThread extends Thread{

           Public void run(){

                 While(!ready)

                      Thread.yield();

                 System.out.println(number);

}

}

 

Public static void main(String[] args){

      New ReaderThread().start();

      Number = 42;

      Ready = true;

}

}

因为没有进行适当的同步, ready 的值为 true ,对读线程来说, ready 的值可能永远不可见,甚至 NoVisibility 可能会打印出 0. 因为早在对 number 赋值之前,主线程就已经写入 ready 并使之对读线程可见,这是一种“重排序 (Reordering) ”现象。

 

详见关于重排序的说明。

1.1 过期数据

当一个线程调用 set ,另外一个线程调用 get ,读线程和可能得到一个过期的数据:

@NotThreadSafe

Public class MutableInteger{

      Private int value;

      Public int get(){     return value;     }

      Public void set(int value){    this.value=value;   }

}

通过 Java 的同步机制,可以保证可见性,保证强的一致性(可以立即看到更新后的结果)

@ThreadSafe

Public class MutableInteger{

      Private int value;

      Public synchronized int get(){       return value;     }

      Public synchronized void set(int value){this.value=value;}

}

 

1.2 非原子的 64 位操作

Java 存储模型要求获取和存储操作都为原子的,但是对于非 volatile long double 变量, JVM 允许将 64 位的读或写划分为两个 32 位操作。如果读和写发生在不同的线程,这种情况读取了一个非 volatile 类型 long 就可能得到一个值的高 32 位和另一个值的低 32 位。

 

 

1.3 Volatile 变量是有代价的

现代处理器的发展,让 CPU 的处理能力得到了质的飞跃,这一切都与 cpu 的高速缓存有关系,这就是为什么 Java 内存模型里面,为什么各自线程有自己的工作内存的原因了,另外也由于直接操作主存,需要耗费更多的 CPU 时钟周期,但是如果存在线程安全问题, volatile 不会使用运行线程所在的 CPU 里面的缓存来读取和写输入, volatile 直接操作的是主存。因此实际上, volatile 为了保全可见性,也牺牲了很多性能。

 

 

2. 发布和逸出

发布 一个对象指的是使它能够被当前范围之外的代码所使用。比如讲一个引用存储到其他代码可以访问的地方,在一个非私有的方法中返回这个引用,也可以把它传递给其它的方法。

 

逸出 指的是一个对象在尚未准备好时就将他发布。

 

不正确的发布对象 - 范围逸出:任何一个调用者都可以修改他的内容,在下例中,数组逸出了它所属的范围。这个本应该是私有的数据,事实上已经变成公有的了。

Public class  UnsafeStates{

      Private String[] states = new String[]{“AK”,”AL”,...;

      Public String[] getStates(){return states;}

}

不正确的发布对象 -This 引用在构造时逸出,当对象并没有完全构造好就被新线程使用。

Public class ThisEscape{

Public ThisEscape(){

      New Thread(){

                 Public void   run(){

                      doSomething();

doSomething1();

                 }

           }).start();

}

 

注意对象只有通过构造函数返回后,才处于可预言的、稳定的状态,所以从构造函数内部发布的对象只是一个未完成构造的对象。甚至即使是在构造函数的最后一行发布的引用也是如此。

 

3. 线程封闭

3.1   栈限制

栈限制是线程限制的一种特例,在栈限制中,只能通过本地变量才可以触及对象,本地变量使对象更容易被限制在线程本地中。本地变量本身就被限制在执行线程中;它们存在于执行线程栈。

3.2   ThreadLocal

ThreadLocal 把变量限制在线程内访问,这样两个线程之间不存在共享访问的问题,两个线程各自维护自己的变量。下面的例子说明了,一个原本可以被多线程法访问的变量,经过 ThreadLocal 的改进,变成了只有当前线程才能访问和修改的变量,这样做自然线程就安全了。

public class ThreadLocalImageServlet extends HttpServlet{

      public ThreadLocal<String> imageURL = new ThreadLocal<String>(){

           public String initialValue(){

                 return "";

           }

      };

      protected void doGet(HttpServletRequest req, HttpServletResponse resp)

                 throws ServletException, IOException {

           imageURL.set(req.getParameter("imageURL"));

           resp.getWriter().println(imageURL.get());

      }

}

3.3   不可变性

 

 

分享到:
评论

相关推荐

    Java并发编程常识-梁飞.rar

    首先,我们来探讨Java并发编程的基础概念。并发是指多个执行单元(线程或进程)在同一时间间隔内同时进行工作。在Java中,我们主要通过线程来实现并发。Java提供了多种创建和管理线程的方法,如Thread类、Runnable...

    Java 并发编程实战-随书源码

    《Java并发编程实战》这本书是Java开发者深入理解并发编程的重要参考书籍。本书旨在帮助程序员解决在多线程环境中遇到的实际问题,提升系统性能并保证其稳定性。随书源码提供了丰富的示例,让读者能够动手实践,加深...

    读书笔记-Java并发编程实战-基础篇

    在Java并发编程中,数据的封装与访问控制、线程安全性的考量、同步机制的使用是重要的基础概念和技巧。以下是从给出的文件内容中提取出的详细知识点: 1. 数据封装与访问控制:确保内部私有数据不被轻易访问,并且...

    JAVA并发编程实践-线程对象与组合对象-学习笔记

    使用java.util.concurrent类库构造安全的并发应用程序的基础。共享其实就是某一线程的数据改变对其它线程可见,否则就会出现脏数据。

    Java并发编程实践--电子书.rar

    《Java并发编程实践》这本书是Java开发者深入理解并发编程的重要参考资料。...通过阅读这本书,你可以深入理解Java并发编程的理论和实践,提升你的编程能力,为构建高并发、高性能的系统打下坚实基础。

    JAVA并发编程实践-

    根据提供的信息,我们可以推断出该资源主要关注的是“Java并发编程实践”的相关内容,并且它是一本高清晰度的PDF电子书。虽然提供的链接部分似乎只是重复的网站地址,我们仍可以根据标题、描述以及标签来生成相关的...

    Java并发编程实战-读书笔记

    《Java并发编程实战》个人读书笔记,非常详细: 1 简介 2 线程安全性 3 对象的共享 4 对象的组合 5 基础构建模块 6 任务执行 7 取消与关闭 8 线程池的使用 9 图形用户界面应用程序 10 避免活跃性危险 11 性能与可...

    Java 并发编程实战.pdf

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

    java并发编程1-9章

    《Java并发编程1-9章》是一份涵盖了Java并发编程核心知识的资料集合,主要源自博客作者Yishizhu在iteye上的分享。通过阅读这些章节,我们可以深入了解Java平台上的多线程和并发处理机制,这对于任何需要处理高性能、...

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

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

    [原]Java并发编程实践-读书笔记

    《Java并发编程实践》这本书是Java开发者...这些知识点构成了Java并发编程的基础,理解和掌握它们对于编写高效、稳定的多线程Java应用程序至关重要。在实际编程中,要根据具体需求灵活应用,并注意性能和安全性的平衡。

    JAVA并发编程实践-线程安全-学习笔记

    在Java并发编程中,线程安全是一个至关重要的概念,它涉及到多线程环境下对共享数据的正确管理和访问。线程安全意味着当多个线程同时访问一个对象或数据时,对象的状态能够保持一致性和完整性,不会因为并发导致数据...

    java并发编程内部分享PPT

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

Global site tag (gtag.js) - Google Analytics