一个类如果想要满足线程安全的条件:

  1. 每个线程都能正常的执行原子操作,保证得到正确的结果
  2. 这个类的对象可以同时被多个线程安全的访问
  3. 在每个线程的原子操作都完成后,对象处于合理的状态

一般情况下不可变类总是线程安全的,因为他的对象的状态始终不会改变,任何线程只能读取他的状态,而不能改变他的状态,例如String类就是一个不可变类,因为String类在我们的代码中使用的实在是太多了,如果设计成可变类后果可想而知……对于那些可变类,如果想要保证它的们的线程安全,就要保证对于他们的原子操作进行同步。

我们常说StirngBuffer是线程安全的,StringBuilder是线程不安全的,为什么呢?因为在StringBuffer类中大量使用了同步,以下只是一小部分方法,方法都用synchronized关键字修饰,做到同步

但是大量运用同步可能对性能造成影响,同步的意思好比大家一起排队做某件事,举个例子i,有十个人去吃饭,但是饭店的座位只有一个,只能一个一个吃,第一个人先吃,这样依次下去,那么第十个人要等到前面九个人都吃完了才能吃饭,想想是不是很委屈。对可变类实现同步往往都会降低并发性能,为了减少带来的影响,我们可以采取下面的措施:

  1. 只对额能导致资源竞争的代码进行同步处理,对于那些没有资源竞争的代码不进行处理,例如我们在对一个属性提供set和get方法的时候,试着只提供get方法获取值,不提供set方法修改值,这样虽然好多个线程同时访问,也不会造成数据的错误和资源的竞争。
  2. 对于多线程环境下我们提供一个运行方式,对于单线程环境下提供一个运行方式。一个类提供两种实现方式,在单线程运行环境下采用微进行同步实现的代码,对于对线程运行环境下采用进行同步处理的代码,避免一刀切。这里有个很好的例子,Map,Set,List这三个集合类都是线程不安全的,在多线程环境下怎么办呢?Collections类提供了很好的解决办法,他提供了返回这些集合同步版本的静态内部类,并在类中重写了集合中所有有资源竞争的方法,加了synchronized关键字进行同步处理

SynchronizedCollection和三个集合一样,也是实现了同步的方法,看代码:

public static <T> List<T> synchronizedList(List<T> list) {
return (list instanceof RandomAccess ?
new SynchronizedRandomAccessList<>(list) :
new SynchronizedList<>(list));
} static <T> List<T> synchronizedList(List<T> list, Object mutex) {
return (list instanceof RandomAccess ?
new SynchronizedRandomAccessList<>(list, mutex) :
new SynchronizedList<>(list, mutex));
} /**
* @serial include
*/
static class SynchronizedList<E>
extends SynchronizedCollection<E>
implements List<E> {
private static final long serialVersionUID = -7754090372962971524L; final List<E> list; SynchronizedList(List<E> list) {
super(list);
this.list = list;
}
SynchronizedList(List<E> list, Object mutex) {
super(list, mutex);
this.list = list;
} public boolean equals(Object o) {
if (this == o)
return true;
synchronized (mutex) {return list.equals(o);}
}
public int hashCode() {
synchronized (mutex) {return list.hashCode();}
} public E get(int index) {
synchronized (mutex) {return list.get(index);}
}
public E set(int index, E element) {
synchronized (mutex) {return list.set(index, element);}
}
public void add(int index, E element) {
synchronized (mutex) {list.add(index, element);}
}
public E remove(int index) {
synchronized (mutex) {return list.remove(index);}
} public int indexOf(Object o) {
synchronized (mutex) {return list.indexOf(o);}
}
public int lastIndexOf(Object o) {
synchronized (mutex) {return list.lastIndexOf(o);}
} public boolean addAll(int index, Collection<? extends E> c) {
synchronized (mutex) {return list.addAll(index, c);}
} public ListIterator<E> listIterator() {
return list.listIterator(); // Must be manually synched by user
} public ListIterator<E> listIterator(int index) {
return list.listIterator(index); // Must be manually synched by user
} public List<E> subList(int fromIndex, int toIndex) {
synchronized (mutex) {
return new SynchronizedList<>(list.subList(fromIndex, toIndex),
mutex);
}
}
public static <T> Set<T> synchronizedSet(Set<T> s) {
return new SynchronizedSet<>(s);
} static <T> Set<T> synchronizedSet(Set<T> s, Object mutex) {
return new SynchronizedSet<>(s, mutex);
} /**
* @serial include
*/
static class SynchronizedSet<E>
extends SynchronizedCollection<E>
implements Set<E> {
private static final long serialVersionUID = 487447009682186044L; SynchronizedSet(Set<E> s) {
super(s);
}
SynchronizedSet(Set<E> s, Object mutex) {
super(s, mutex);
} public boolean equals(Object o) {
if (this == o)
return true;
synchronized (mutex) {return c.equals(o);}
}
public int hashCode() {
synchronized (mutex) {return c.hashCode();}
}
}

我们可以通过代码看到他是实现了一个静态方法,在静态方法中去创建这个静态类,而这个静态类重写了集合中有资源竞争关系的方法(加了同步处理)

参考:Java面向对象编程--孙卫琴

实现Java线程安全的更多相关文章

  1. Java线程并发:知识点

    Java线程并发:知识点   发布:一个对象是使它能够被当前范围之外的代码所引用: 常见形式:将对象的的引用存储到公共静态域:非私有方法中返回引用:发布内部类实例,包含引用.   逃逸:在对象尚未准备 ...

  2. Java线程的概念

    1.      计算机系统 使用高速缓存来作为内存与处理器之间的缓冲,将运算需要用到的数据复制到缓存中,让计算能快速进行:当运算结束后再从缓存同步回内存之中,这样处理器就无需等待缓慢的内存读写了. 缓 ...

  3. Java 线程池框架核心代码分析--转

    原文地址:http://www.codeceo.com/article/java-thread-pool-kernal.html 前言 多线程编程中,为每个任务分配一个线程是不现实的,线程创建的开销和 ...

  4. 细说进程五种状态的生老病死——双胞胎兄弟Java线程

    java线程的五种状态其实要真正高清,只需要明白计算机操作系统中进程的知识,原理都是相同的. 系统根据PCB结构中的状态值控制进程. 单CPU系统中,任一时刻处于执行状态的进程只有一个. 进程的五种状 ...

  5. 【转载】 Java线程面试题 Top 50

    Java线程面试题 Top 50 不管你是新程序员还是老手,你一定在面试中遇到过有关线程的问题.Java语言一个重要的特点就是内置了对并发的支持,让Java大受企业和程序员 的欢迎.大多数待遇丰厚的J ...

  6. 第24章 java线程(3)-线程的生命周期

    java线程(3)-线程的生命周期 1.两种生命周期流转图 ** 生命周期:**一个事物冲从出生的那一刻开始到最终死亡中间的过程 在事物的漫长的生命周期过程中,总会经历不同的状态(婴儿状态/青少年状态 ...

  7. 第23章 java线程通信——生产者/消费者模型案例

    第23章 java线程通信--生产者/消费者模型案例 1.案例: package com.rocco; /** * 生产者消费者问题,涉及到几个类 * 第一,这个问题本身就是一个类,即主类 * 第二, ...

  8. 第22章 java线程(2)-线程同步

    java线程(2)-线程同步 本节主要是在前面吃苹果的基础上发现问题,然后提出三种解决方式 1.线程不安全问题 什么叫线程不安全呢 即当多线程并发访问同一个资源对象的时候,可能出现不安全的问题 对于前 ...

  9. 第21章 java线程(1)-线程初步

    java线程(1)-线程初步 1.并行和并发 并行和并发是即相似又有区别: 并行:指两个或者多个事件在同一时刻点发生. 并发:指两个或多个事件在同一时间段内发生 在操作系统中,并发性是指在一段事件内宏 ...

  10. [转]Java线程安全总结

    最近想将java基础的一些东西都整理整理,写下来,这是对知识的总结,也是一种乐趣.已经拟好了提纲,大概分为这几个主题: java线程安全,java垃圾收集,java并发包详细介绍,java profi ...

随机推荐

  1. LinkedHashMap概述

    1. LinkedHashMap概述: LinkedHashMap是HashMap的一个子类,它保留插入的顺序,如果需要输出的顺序和输入时的相同,那么就选用LinkedHashMap. LinkedH ...

  2. localhost直接访问子文件夹无法完成

    刚装上新版的wamp,之前的改动都初始化了,发现了一个问题,localhost不能直接访问子文件夹了,从网上找了找答案,没费事,解决了. 将WWW目录下的index.php打开,更改里面的内容,更改内 ...

  3. 剑指offer 第九天

    35.数组中的逆序对 在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对.输入一个数组,求出这个数组中的逆序对的总数P.并将P对1000000007取模的结果输出. 即输出 ...

  4. ImportError: No module named 'xlrd' 解决办法

    import pandas as pd data = pd.read_excel('工作簿1.xls',sheetname='Sheet1') 用pandas读取Excel文件时,会提示 Import ...

  5. mysql常用基础操作语法(一)~~对库的操作【命令行模式】

    1.创建数据库:create Database databaseName;例如需要创建mysqlTest数据库,create Database mysqlTest; 由此还可以看出,这里的名称是不分大 ...

  6. PL/SQL NOCOPY限制模式

    NOCOPY模式用于限定OUT模式和IN OUT模式在调用时是不是以传引用的方式进行. 默认情况下,OUT模式和IN OUT模式的参数是以传值的方式进行调用的. IN模式总是以传引用的方式,如果用NO ...

  7. Linux显示目前与过去登入系统的用户相关信息

    Linux显示目前与过去登入系统的用户相关信息 youhaidong@youhaidong-ThinkPad-Edge-E545:~$ last youhaido pts/0 :0 Sat Jan 2 ...

  8. c语言 第二次实验报告

    一·实验题目,设计思路,实现方法 11-7 找鞍点 一个矩阵元素的"鞍点"是指该位置上的元素值在该行上最大.在该列上最小. 本题要求编写程序,求一个给定的n阶方阵的鞍点. 利用双重 ...

  9. 初识Windows服务 C#

    1.新建Windows服务   2.切换到代码视图,拷入如下代码 该服务以10S的间隔创建 d:/1.txt 文件 using System; using System.Collections.Gen ...

  10. Python 第二天学习(文件的处理)

    学习的内容是: python的文件处理 列表,元组,字典的使用 集合的使用 函数 文件file.textd的内容 A person with high EQ doesn't often critici ...