博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
怎样去写线程安全的代码(Java)
阅读量:4957 次
发布时间:2019-06-12

本文共 1676 字,大约阅读时间需要 5 分钟。

使用多线程就可能会存在线程安全的问题。很多 java 程序员对写多线程都很挣扎,或者仅仅理解那些是线程安全的代码,那些不是。这篇文章我并不是详述线程安全,详述同步机制的文章,相反我只是用一个简单的非线程安全的代码例子引领大家,然后重点是去理解什么是线程安全,以及怎样使代码变得线程安全。

好了,下面我们先来看一个非线程安全的代码,可以尝试找找为什么非线程安全?

/*
* 非线程安全类
*/  
public class Counter {
private int count;
 
public int getCount(){
       return count++;
   }
}

 

大家应该能看得出来,上面代码是非线程安全的,因为 ++ 操作不是原子操作,读取、更新、写回的时候可能会出问题。

比如现在有多个线程同时访问 getCount() 方法,那么这些线程可能同时操作 count ,部分结果出现重叠。例如,Thread 1 正在更新 count,Thread 2 读取 count,但是仍然是获取到旧的值,那么最后Thread 2 就会覆盖掉 Thead 1 的更新,所以并发环境下我们要考虑 ++ 操作的原子性。 

 

在 Java 编程中,有许多方式去编写线程安全的代码:

1)、使用 synchronized 关键字,synchonized 可以 lock  getCount() 方法,某个时刻只有一个线程可以执行它,也就实现了线程安全

2)、使用原子的 Integer,原子的 Integer 可以保证 ++ 操作的原子性

 

好了,我们了看看线程安全版本的 Counter 

 

public class Counter {
    private int count;
    AtomicInteger atomicCount = new AtomicInteger( 0 );
  
   /*
*1、synchronized 所以线程安全
*/
    public synchronized int getCount(){
        return count++;
    }
  
    /*
     * 2、原子增长的操作,所以线程安全
     */
    public int getCountAtomically(){
        return atomicCount.incrementAndGet();
    }
}
 
java 线程安全比较重要的点:
 
 
在 java 编程中,记住这些关键点可以帮你避免一些严重的并发问题,比如条件竞争或死锁。
1)、不可变对象默认是线程安全的,因为他们一旦被创建就不会被修改。比如 String 是不可变对象,是线程安全的。
 
2)、只读、final 类型的变量也是线程安全的
 
3)、锁也是一种线程安全的方式
 
4) 、static 变量,如果没有被恰当的使用同步,也会引发线程安全问题
 
5)、使用线程安全的类: Vector, Hashtable, ConcurrentHashMap, String etc.
 
6)、原子操作是线程安全的 reading a 32 bit int from memory because its an atomic operation it can‘t interleave with other thread.
 
7) 、本地变量也是线程安全的,因为每个线程都有自己的变量 copy.使用本地变量是一种保证代码线程安全的好方法。(ThreadLocal)
 
8)、 多线程之间的共享对象尽可能的少,也就尽可能的避免线程安全的问题
 
9) 、Volatile 关键字
 
 
好了,以上就是所有的关于编写线程安全类或代码和避免并发问题的要点。老实说,线程安全是有点难掌握的概念,你需要去考虑并发,进而看代码是否线程安全。
当然 jvm 也可以重排序代码,实现自己调优。但是相同的代码在开发环境正常不一定能保证在线上也正常。因为 jvm 会去自我调优,重排序等操作去优化代码,这些也可能会生成线程安全的问题。

转载于:https://www.cnblogs.com/dalen/p/6741659.html

你可能感兴趣的文章
NeHe OpenGL教程 第六课:纹理映射
查看>>
IO 输入输出流
查看>>
Linux下alias命令
查看>>
Win7 安装.net framework 4.0 失败,错误HRESULT 0xc8000222解决办法
查看>>
Spring常用知识点总结
查看>>
golang: 利用unsafe操作未导出变量
查看>>
嘤嘤嘤
查看>>
织梦首页TAG标签页的仿制
查看>>
织梦系统调用点击次数代码优化提高页面打开速度
查看>>
[Leetcode Week13]Search a 2D Matrix
查看>>
通过被调函数改变主调函数的值
查看>>
Spring源码导入IDEA
查看>>
PHP关于VC11,VC9,VC6以及Thread Safe和Non Thread Safe版本选择的问题
查看>>
6、旋转数组的最小位置------------>剑指offer系列
查看>>
2016年第七届蓝桥杯C/C++程序设计本科B组省赛
查看>>
python-day9-循环嵌套
查看>>
python-day46--前端基础之html
查看>>
python技术
查看>>
android 数据存储之SQLite
查看>>
java 对象的序列化与反序列化
查看>>