0

0

Java并发编程之线程安全性怎么实现

WBOY

WBOY

发布时间:2023-05-21 15:14:13

|

1545人浏览过

|

来源于亿速云

转载

    1.什么是线程安全性

    当多个线程访问某个类时,不管运行时环境采用何种调用方式或者这些线程将如何交替执行,并且在主调代码中不需要任何额外的同步或协同,这个类都能表现出正确的行为,那么就称这个类是线程安全的。

    无状态的对象一定是线程安全的,比如:Servlet

    2.原子性

    2.1 竞争条件

    由于不恰当的执行时序而出现不正确的结果的情况,就是竞争条件。

    “先检查后执行”操作,即通过一个可能实效的观测结果来决定下一步的动作。比如:延迟初始化。

    if(instance == null) {
        instance = new SomeObject();
    }

    “读取-修改-写入”的操作,其结果状态依赖于之前的状态。如:递增运算。

    立即学习Java免费学习笔记(深入)”;

    long count = 0;
    count++;

    2.2 复合操作

    原子操作是指,对于访问同一个状态的所有操作(包括此操作本身)来说,这个操作是以一个原子方式执行(不可分割)的操作。

    为了确保线程安全性,包含了一组必须以原子方式执行的操作,称为复合操作。

    递增运算可以使用一个现有的线程安全类,确保线程安全性。如:

    AtomicLong count = new AtomicLong(0);
    count.incrementAndGet();

    3.加锁机制

    如果一个类只有一个状态变量,可以通过使用线程安全的状态变量来确保类的线程安全性。当一个类有更多的状态时,仅仅添加更多的线程安全状态变量是不够的。为了确保状态的一致性,必须在单个原子操作中更新所有相关的状态变量。

    墨鱼aigc
    墨鱼aigc

    一款超好用的Ai写作工具,为用户提供一键生成营销广告、原创文案、写作辅助等文字生成服务。

    下载

    3.1 内置锁

    Java提供一种内置锁:同步代码块,它包括:一个作为锁的对象引用、一个作为由这个锁保护的代码块。

    以关键字synchronized来修饰的方法就是一种横跨整个方法体的同步代码块,其中该同步代码块的锁就是方法调用所在的对象。静态的synchronized方法以Class对象作为锁。

    当线程进入同步代码块时,会自动获取锁;而当线程退出同步代码块时,会自动释放锁。最多只有一个线程能持有这种锁,因此同步代码会以原子方式执行。

    3.2 重入

    内置锁是可重入的,意味着获取锁的操作的粒度是线程,不是调用。当一个线程尝试重新获取已经由其持有的锁时,该请求也会成功。

    重入进一步提升了加锁行为的封装性,简化了面向对象并发代码的开发。

    public class Widget {
        public synchronized void doSomething() {
            //......
        }
    }
    public class LoggingWidget extends Widget {
        public synchronized void doSomething() {
            //......
            super.doSomething();//假如没有可重入的锁,该语句将产生死锁。
        }
    }

    4.用锁保护状态

    对于可能被多个线程同时访问的可变状态变量,在访问它时都需要持有同一个锁,在这种情况下,称状态变量是由这个锁保护的。

    5.活跃性与性能

    粗粒度地使用锁,虽然确保了线程安全性,但可能造成性能问题和活跃度问题,如:

    @ThreadSafe
    public class SynchronizedFactorizer implements Servlet {
        @GuardedBy("this") private BigInteger lastNumber;
        @GuardedBy("this") private BigInteger[] lastFactors;
    
        public synchronized void service(ServletRequest req,
                                         ServletResponse resp) {
            BigInteger i = extractFromRequest(req);
            if (i.equals(lastNumber))
                encodeIntoResponse(resp, lastFactors);
            else {
                BigInteger[] factors = factor(i);//因数分解计算
                lastNumber = i;
                lastFactors = factors;//存放上一次计算结果
                encodeIntoResponse(resp, factors);
            }
        }
    }

    可以通过缩小同步代码块,既确保servlet的并发型,又维护线程安全性。不要把本应是原子操作拆分到多个同步代码块中,尽量将不影响共享状态且执行时间较长的操作从同步代码中分离出来。如:

    public class CachedFactorizer implements Servlet {
        @GuardedBy("this") private BigInteger lastNumber;
        @GuardedBy("this") private BigInteger[] lastFactors;
    
        public void service(ServletRequest req, ServletResponse resp) {
            BigInteger i = extractFromRequest(req); 
            BigInteger[] factors = null;      
            synchronized (this) {
                if (i.equals(lastNumber)) {
                   factors = lastFactors.clone();
                }         
            }    
            if (factors == null) {        
                factors = factor(i);
                synchronized (this) {
                   lastNumber = i;
                   lastFactors = factors.clone();
                }
            }
            encodeIntoResponse(resp, factors);
        }
    }

    相关专题

    更多
    c++ 根号
    c++ 根号

    本专题整合了c++根号相关教程,阅读专题下面的文章了解更多详细内容。

    17

    2026.01.23

    c++空格相关教程合集
    c++空格相关教程合集

    本专题整合了c++空格相关教程,阅读专题下面的文章了解更多详细内容。

    22

    2026.01.23

    yy漫画官方登录入口地址合集
    yy漫画官方登录入口地址合集

    本专题整合了yy漫画入口相关合集,阅读专题下面的文章了解更多详细内容。

    91

    2026.01.23

    漫蛙最新入口地址汇总2026
    漫蛙最新入口地址汇总2026

    本专题整合了漫蛙最新入口地址大全,阅读专题下面的文章了解更多详细内容。

    124

    2026.01.23

    C++ 高级模板编程与元编程
    C++ 高级模板编程与元编程

    本专题深入讲解 C++ 中的高级模板编程与元编程技术,涵盖模板特化、SFINAE、模板递归、类型萃取、编译时常量与计算、C++17 的折叠表达式与变长模板参数等。通过多个实际示例,帮助开发者掌握 如何利用 C++ 模板机制编写高效、可扩展的通用代码,并提升代码的灵活性与性能。

    14

    2026.01.23

    php远程文件教程合集
    php远程文件教程合集

    本专题整合了php远程文件相关教程,阅读专题下面的文章了解更多详细内容。

    65

    2026.01.22

    PHP后端开发相关内容汇总
    PHP后端开发相关内容汇总

    本专题整合了PHP后端开发相关内容,阅读专题下面的文章了解更多详细内容。

    59

    2026.01.22

    php会话教程合集
    php会话教程合集

    本专题整合了php会话教程相关合集,阅读专题下面的文章了解更多详细内容。

    61

    2026.01.22

    宝塔PHP8.4相关教程汇总
    宝塔PHP8.4相关教程汇总

    本专题整合了宝塔PHP8.4相关教程,阅读专题下面的文章了解更多详细内容。

    33

    2026.01.22

    热门下载

    更多
    网站特效
    /
    网站源码
    /
    网站素材
    /
    前端模板

    精品课程

    更多
    相关推荐
    /
    热门推荐
    /
    最新课程
    Kotlin 教程
    Kotlin 教程

    共23课时 | 2.8万人学习

    C# 教程
    C# 教程

    共94课时 | 7.4万人学习

    Java 教程
    Java 教程

    共578课时 | 50.3万人学习

    关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
    php中文网:公益在线php培训,帮助PHP学习者快速成长!
    关注服务号 技术交流群
    PHP中文网订阅号
    每天精选资源文章推送

    Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号