并发编程六:线程安全与共享资源

    xiaoxiao2025-04-05  33

    线程安全与共享资源

    介绍

    允许被多个线程同时执行的代码称作线程安全的代码。线程安全的代码不包含竞态条件。 弄清楚Java线程执行时共享了哪些资源非常的重要

    共享资源

    局部变量

    局部变量存储在线程自己的栈中.也就是说,局部变量永远也不会被多个线程共享。所以,基础类型的局部变量是安全的.
    public int fun(){ int a=10; return a; } 这个方法就是线程安全的

    局部的对象引用

    对象的局部引用和基础类型的局部变量不太一样.尽管引用本身没有被共享.但引用所指的对象并没有存储在线程的栈内. 所有的对象都存在共享堆中. 如果在某个方法中创建的对象不会逃逸出(即该对象不会被其它方法获得,也不会被非局部变量引用到)该方法,那么它就是线程安全的.
    public void fun(){ Object obj=new Object(); //obj do ... } //这个方法即使是局部对象引用也是线程安全的,因为每一个线程都会创建一个新的Object对象。

    对象成员(即成员变量)

    对象成员存储在堆上.如果两个线程同时更新同一个对象的同一个成员,那这个代码就不是线程安全的. 以下这段方法代码就不是线程安全的,需要我们作同步处理。
    private int count = 0; public int incr() { return (++count); }

    线程控制逃逸规则

    如果一个资源的创建、使用、销毁都在同一个线程内完成,且永远不会脱离该线程的控制,则该资源的使用就是线程安全的. 资源可以是对象、数组、文件、数据库连接、套接字等等.Java中你无需主动销毁对象,所以“销毁”指不再有引用指向对象。
    即使对象本身线程安全,但如果该对象中包含其他资源(文件,数据库连接)整个应用也许就不再是线程安全的了 比如2个线程都创建了各自的数据库连接,每个连接自身是线程安全的,但它们所连接到的同一个数据库也许不是线程安全的 2个线程执行如下代码 检查记录X是否存在,不存在则插入X 如果两个线程并发执行可能的情景: A线程检查记录X是否存在。结果不存在 B线程检查记录X是否存在。结果不存在 A线程插入记录 B线程插入记录 这样就会出现重复插入问题了。 同样的问题也会发生在文件或其他共享资源上.因此,区分某个线程控制的对象是资源本身,还是仅仅到某个资源的引用很重要。

    总结

    线程安全问题首先要分析共享资源是什么,有时除了程序上的共享资源,还得考虑文件、数据库等资源。

    参考

    1、http://tutorials.jenkov.com/java-concurrency/thread-safety.html

    转载请注明原文地址: https://ju.6miu.com/read-1297761.html
    最新回复(0)