前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >笔记 35 | java线程之线程安全与非线程安全

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

作者头像
项勇
发布于 2018-06-19 07:22:16
发布于 2018-06-19 07:22:16
62600
代码可运行
举报
文章被收录于专栏:项勇项勇
运行总次数:0
代码可运行

地址

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关键字来修饰该方法即可:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class counnt{
        private int count = 0;

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

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

例子理解:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public Double dou(){
        int a = 5;
        int b = 2;
        return new Double(a/b);
    }

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

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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出一个脏的数据。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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倍左右,如果不加的话,该类的成员变量又可能发生错误,所以具体就看你的需求,一个是否有很多线程操作这个方法,一个是否注重它的性能!

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2017-11-16,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 项勇 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
面试官:单例Bean一定不安全吗?实际工作中如何处理此问题?
默认情况下,Spring Boot 中的 Bean 是非线程安全的。这是因为,默认情况下 Bean 的作用域是单例模式,那么此时,所有的请求都会共享同一个 Bean 实例,这意味着这个 Bean 实例,在多线程下可能被同时修改,那么此时它就会出现线程安全问题。
磊哥
2024/01/11
4130
面试官:单例Bean一定不安全吗?实际工作中如何处理此问题?
Java 并发核心机制
Java 的 java.util.concurrent 包(简称 J.U.C)中提供了大量并发工具类,是 Java 并发能力的主要体现(注意,不是全部,有部分并发能力的支持在其他包中)。从功能上,大致可以分为:
静默虚空
2020/01/02
4760
(82) 理解ThreadLocal / 计算机程序的思维逻辑
本节,我们来探讨一个特殊的概念,线程本地变量,在Java中的实现是类ThreadLocal,它是什么?有什么用?实现原理是什么?让我们接下来逐步探讨。 基本概念和用法 线程本地变量是说,每个线程都有同一个变量的独有拷贝,这个概念听上去比较难以理解,我们先直接来看类TheadLocal的用法。 ThreadLocal是一个泛型类,接受一个类型参数T,它只有一个空的构造方法,有两个主要的public方法: public T get() public void set(T value) set就是设置值,
swiftma
2018/01/31
6000
Java多线程第二篇-线程的常用方法和线程安全
如果多个线程执行上述的代码,因为线程的调度顺序是“随机”的,因在count++中会执行N次而且三个指令的cpu指令顺序不同,就会导致在有些调度顺序下,并发程度高,上述逻辑就会出现问题。
如烟花般绚烂却又稍纵即逝
2024/12/26
660
Java多线程第二篇-线程的常用方法和线程安全
通俗易懂讲解Java线程安全
一个非科班的技术男,自学半年找到了份不错的程序员工作,运营维护订阅号「一个程序员的成长」希望做一个专注于Java领域的公众号,喜欢本文章可以搜索关注。
用户1093975
2018/09/21
6380
通俗易懂讲解Java线程安全
Java线程安全与并发问题
多线程编程在Java中是一个常见的需求,它可以提高程序的性能和响应能力。然而,多线程编程也带来了一系列的线程安全与并发问题。在本文中,我们将深入探讨这些问题,以及如何解决它们,适用于Java初学者和基础用户。
长乐坡头
2024/01/11
1630
【Java多线程】线程安全及解决方案(详解)
因为多个线程并发执行,引起的bug,这样的bug称为“线程安全问题”或者叫做“线程不安全”
用户11369558
2024/11/20
1290
【Java多线程】线程安全及解决方案(详解)
Java多线程之线程安全问题
原文:https://blog.csdn.net/weixin_59383491/article/details/134952020
一百减一是零
2024/08/08
1970
线程安全性---面试题--i++的线程安全性问题
AtomicInteger,一个提供原子操作的Integer的类。在Java语言中,++i和i++操作并不是线程安全的,在使用的时候,不可避免的会用到synchronized关键字。而AtomicInteger则通过一种线程安全的加减操作接口。
wust小吴
2019/07/08
7560
ThreadLocal详解
保证线程安全一是可以同步对共享资源的操作和访问,二是不共享。就像ThreadLocal这样,给每个线程分一个对象,每个线程也只能访问到自己的这个对象,从而保证线程安全。比如SimpleDateFormat这个类,咋也没想到它是线程不安全的,既然线程不安全我们就给每一个线程都实例化一个SimpleDateFormat,自己用自己的就安全了,ThreadLocal就给我们实现了分配线程私有对象这么个功能。
naget
2019/07/03
4230
ThreadLocal详解
线程池如何传递线程上下文信息
线程池的线程上下文传递,实现方案就是在提交任务时记录当前线程上下文信息,在线程池中线程执行用户任务前将之前保存的上下文塞到当前线程的上下文中,在执行用户任务之后移除该上下文即可。简单来说就是,外部线程提交任务时要记录上下文信息,内部线程执行任务时获取之前记录的上下文信息设置到当前线程上下文中。
luoxn28
2020/03/25
3K0
Java并发编程(4)- 线程安全策略
有一种对象发布了就是安全的,这就是不可变对象,本小节简单介绍一下不可变对象。不可变对象可以在多线程在保证线程安全,不可变对象需要满足的条件:
端碗吹水
2020/09/23
5460
Java并发编程(4)- 线程安全策略
Java并发编程(2)- 线程安全性详解
说到原子性,就不得不提及JDK里的atomic包,该包中提供了很多Atomic的类,本小节主要介绍该包中常用的几个类。这些类都是通过CAS来实现原子性的,atomic包提供了如下具有原子性的类:
端碗吹水
2020/09/23
3380
Java并发编程(2)- 线程安全性详解
并发业务中,线程安全与否很重要,来看看你懂多少?
链接: https://juejin.im/post/5b7d68f66fb9a019d80a9002
Java小咖秀
2020/07/15
3870
并发业务中,线程安全与否很重要,来看看你懂多少?
设计模式 | 创建型 | 单例模式
一个类只允许创建一个对象(或者实例),那这个类就是一个单例类,这种设计模式就叫作单例设计模式,简称单例模式。
被水淹没
2023/02/25
4470
设计模式 | 创建型 | 单例模式
Java多线程(一篇从0讲透)
进程:是指一个内存中运行的程序,每个进程都有一个独立的内存空间,一个应用程序可以同时运行多个进程
不吃紫菜
2023/04/02
3750
Java多线程(一篇从0讲透)
并发编程之多线程线程安全
当多个线程同时共享,同一个全局变量或静态变量,做写的操作时,可能会发生数据冲突问题,也就是线程安全问题。但是做读操作是不会发生数据冲突问题。
蒋老湿
2019/07/31
1K0
Java多线程编程
一个线程就是一个 “执行流”. 每个线程之间都可以按照顺讯执行自己的代码. 多个线程之间 “同时” 执行 着多份代码
用户9645905
2023/10/23
2410
Java多线程编程
【多线程-从零开始-肆】线程安全、加锁和死锁
在多个线程同时执行某个代码的时候,可能会引起一些奇怪的 bug。理解了线程安全,才能避免/解决上述的 bug
椰椰椰耶
2024/09/21
1280
【多线程-从零开始-肆】线程安全、加锁和死锁
Java线程安全面试题,你真的了解吗?
多个线程不管以何种方式访问某个类,并且在主调代码中不需要进行同步,都能表现正确的行为。
李红
2019/05/30
3200
Java线程安全面试题,你真的了解吗?
相关推荐
面试官:单例Bean一定不安全吗?实际工作中如何处理此问题?
更多 >
领券
社区富文本编辑器全新改版!诚邀体验~
全新交互,全新视觉,新增快捷键、悬浮工具栏、高亮块等功能并同时优化现有功能,全面提升创作效率和体验
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文