笔记 35 | java线程之线程安全与非线程安全

地址

CSDN http://blog.csdn.net/xiangyong_1521/article/details/78541142


线程安全与非线程安全

ArrayList和VectorHashMap和HashTableStringBuilder和StringBuffer这些有什么区别?

这些面试题常被问,答案是,左边的都是非线程安全,右边都是线程安全!

然后又问你,什么是线程安全,什么是非线程安全呢?

A.线程安全

当多个线程类并发操作某类的方法A,来修改这个A方法的某个成员变量的值B,B不会出错,则我们就说,该的这个A方法是线程安全的。   某类的某方法是否线程安全的关键是:   (1) 该方法是否修改该类的成员变量;   (2) 是否给该方法加锁(是否用synchronized关键字修饰)。

B.非线程安全

当多个线程类并发操作某类的方法A,来修改这个A方法的某个成员变量的值B,B会出错,则我们就说,该的这个A方法是非线程安全的。


synchronized

如果要把这个方法变成线程安全的,则用 synchronized关键字来修饰该方法即可:

class counnt{
        private int count = 0;

        /*
         * 当有多个线程类同时操作这个方法是,就容易出问题
         */
        public void add(){
            count++;
        }

        /*
         * 当加了synchronized修饰后,就是线程安全的了,不过性能很低
         */
        public synchronized void adds(){
            count++;
        }
    }

例子理解:

public Double dou(){
        int a = 5;
        int b = 2;
        return new Double(a/b);
    }

在执行这个方法时,每一个线程都有自己的独立的栈区。当线程进入到方法执行断的时候,一个方法变量在方法代码段中被创建,并保存在线程的栈区(静态方法也放在这里)。不同线程执行这段代码时,会有不同的a/b变量。所以这里是线程安全的,因为没有数据共享。

考虑下面的例子,多线程情况下只执行一次并可以重用结果:

private Double dou;
    public Double dou(){
        int a = 5;
        int b = 2;
        if (dou == null) {
            dou = new Double(a/b);
        }
        return dou;
    }

这个地方虽然优化了,但可惜他不是线程安全的。两个线程并发执行的时候同时进入到dou ==null这个位置,这样可能会new出一个脏的数据。

private static ThreadLocal local = new ThreadLocal();
    public Double dou(){
        int a = 5;
        int b = 2;
        if (local.get() == null) {
            local.set(new Double(a/b));
        }
        return (Double)local.get();
    }

ThreadLocal类封装了任何类型对象,并把它绑定到当前线程。线程执行dou()方法的时候,实例pi返回的是当前线程的对象。这样的调用是线程安全的。

线程安全跟非线程安全如何取舍

从第一个例子可得知,非线程的方法添加synchronized修饰就可以转化为线程安全,但是性能会相差20倍左右,如果不加的话,该类的成员变量又可能发生错误,所以具体就看你的需求,一个是否有很多线程操作这个方法,一个是否注重它的性能!

原文发布于微信公众号 - 项勇(xiangy_life)

原文发表时间:2017-11-16

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏二进制文集

JDK源码分析 多线程

对于JDK源码分析的文章,仅仅记录我认为重要的地方。源码的细节实在太多,不可能面面俱到地写清每个逻辑。所以我的JDK源码分析,着重在JDK的体系架构层面,具体源...

682
来自专栏积累沉淀

死锁

什么是死锁: 是指两个或两个以上的进程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死...

1819
来自专栏java一日一条

Java 并发开发:内置锁 Synchronized

在多线程编程中,线程安全问题是一个最为关键的问题,其核心概念就在于正确性,即当多个线程访问某一共享、可变数据时,始终都不会导致数据破坏以及其他不该出现的结果。而...

392
来自专栏你不就像风一样

Java多线程编程核心技术(三)多线程通信

通过本节可以学习到,线程与线程之间不是独立的个体,它们彼此之间可以互相通信和协作。

958
来自专栏你不就像风一样

深入理解[Future模式]原理与技术

在程序设计中,当某一段程序提交了一个请求,期望得到一个答复。但非常不幸的是,服务程序对这个请求的处理可能比较慢,比如,这个请求可能是通过互联网、HTTP或者We...

662
来自专栏用户3030674的专栏

java线程控制安全

在线程运行的时候,有时会出现线程安全问题 例如:买票程序,有可能会出现不同窗口买同一张编号的票

560
来自专栏Java技术栈

Java多线程神器:join使用及原理

join() join()是线程类 Thread的方法,官方的说明是: Waits for this thread to die. 等待这个线程结束,也就是说当...

3295
来自专栏互联网开发者交流社区

java 多线程学习

802
来自专栏函数式编程语言及工具

Scalaz(45)- concurrency :Task-函数式多线程编程核心配件

    我们在上一节讨论了scalaz Future,我们说它是一个不完善的类型,最起码没有完整的异常处理机制,只能用在构建类库之类的内部环境。如果scalaz...

2506
来自专栏电光石火

java 线程public void run()中值如何返回

Executor 接口 执行已提交的 Runnable 任务的对象。此接口提供一种将任务提交与每个任务将如何运行的机制(包括线程使用的细节、调度等)分离开来的方...

3357

扫码关注云+社区