精华内容
下载资源
问答
  • 2019-12-22 16:34:43

    java语言线程的安全可以按照安全程度分为五个等级:

    一 不可变

    1.不可变的对象一定是线程安全的,无论是对象的方法实现还是调用者,都不需要再采取任何的线程安全保障措施。

    2.不可变带来的安全性是最纯粹的最简单的。

    3.final关键字就可以做到不可变。

    二 绝对的线程安全

    1. 不管运行时环境如何,调用者都不需要任何额外的同步措施。

    2.通常代价是很大的,容易不切实际。

    3.API中标注自己是线程安全的类,大多数都不是绝对的线程安全。比如vector

    三 相对的线程安全

    1.通常来说线程是安全的,但对于一些特定顺序的连续调用,就可能需要在调用端使用额外的同步手段来保证调用的正确性。

    2.大部分线程都属于这种类型,如vector

    四 线程兼容

    本身不是线程安全的,但是可以通过调用端使用同步来保证安全性。

    五 线程对立

    无论是否采用同步措施,都无法在并发中使用。

    更多相关内容
  • 文章目录线程安全与锁优化一、线程安全概念不可变绝对线程安全相对线程安全线程兼容线程对立二、线程安全的实现方法互斥同步最基本互斥手段就是synchronized另一种手段JUC下的ReentrantLock阻塞同步的问题:非阻塞...

    线程安全与锁优化

    一、线程安全概念

    为了更好的理解线程安全,我们不把线程安全看做是一个二元对立的选项来看,而是按照线程安全的”安全程度“由强至弱来排序。

    Java线程各种操作共享的数据分为五类:

    • 不可变
    • 绝对线程安全
    • 相对线程安全
    • 线程兼容
    • 线程对立

    不可变

    不可变的对象一定是线程安全的,无论是对象的方法实现还是方法的调用者,都不需要进行任何的线程安全保障措施。被final修饰的对象只要被正确构建出来,就永远是不可变的,也就是线程安全的。

    • 例1-1:

    String类型就是不可变类型,我们调用它的substring()、replace()方法都不会影响原来的值,只会返回一个新构造的字符串对象。

    绝对线程安全

    不管运行环境如何,调用者也不需要任何的同步措施,就可以达到线程安全。这种状态通常不可能达到或要付出非常大的代价。

    • 例1-2:

    Vector是一个线程安全的容器,但是仍然会出错。

    //线程一执行:
    for(int i=0;i<vector.size();i++){
        vector.remove(i);
    }
    //线程二执行
    for(int i=0;i<vector.size();i++){
        vector.get(i);
    }
    

    该情况下,可能在线程二执行了i++之后执行get(i)之前被阻塞调用了线程一,之后i位置的元素被移除了,此时线程二执行get(i)就会出错

    相对线程安全

    普遍意义上的线程安全,它保证对象单独的操作时线程安全的,但是对于一些特定顺序的连续调用就可能需要在调用端使用额外的同步手段来保证调用正确性。例1-2就是一个很好的例子。

    绝大部分线程安全类都属于这种类型。如Vector、HashTable、Collections的synchronizedCollection()方法包装的集合

    线程兼容

    线程兼容是指对象本身并不是线程安全的,但是可以通过调用端正确地使用同步手段保证对象可以在并发环境中使用。

    如ArrayList和HashMap就是线程兼容的。可以自行添加锁来保证安全

    线程对立

    无论是否采取同步措施,都无法在多线程环境下保证并发。

    如采取同步措施后出现的死锁问题

    二、线程安全的实现方法

    实现线程安全的方法有三种

    • 互斥同步
    • 非阻塞同步
    • 无同步

    互斥同步

    互斥同步是最常见的一种并发正确性保障手段。

    • 同步是指多个线程并发访问共享数据时,保证共享数据在同一时刻只被一条(或一些,使用信号量的时候)线程使用。
    • 互斥是实现同步的一种手段,临界区、互斥量、信号量都是主要实现方式

    互斥是因,同步是果。互斥是方法,同步是目的。

    最基本互斥手段就是synchronized

    synchronized关键字经过编译之后会在同步代码块的前后分别形成monitorenter和monitorexit这两个字节码指令。这两个字节码都需要一个reference类型的参数来指明要锁定和解锁的对象

    目前简易执行流程,与实际执行有出入

    在这里插入图片描述

    缺点:

    • 由于Java的线程是映射到操作系统的原生线程之上,如果阻塞和唤醒一条线程就需要从用户态转换到核心态,需要耗费处理器较多时间。如对于简单的同步块进行内核状态转换消耗的时间可能比业务代码执行时间还要长,使系统的性能较低。是一个重量级操作

      后期会优化在阻塞前加入一段自旋等待的过程,避免频繁切换状态。

    另一种手段JUC下的ReentrantLock

    在基本用法上ReentrantLock与synchronized很相似。都具备可重入性。

    区别:

    • ReentrantLock是表现在API层面的互斥锁,synchronized是表现在原生语法层面的互斥锁
    • ReentrantLock获取锁的等待可以被中断,synchronized不可以被中断
    • ReentrantLock可以实现公平锁(默认为非公平锁),synchronized则只能是非公平锁
    • ReentrantLock可以精确进行线程唤醒,synchronized只能粗略的进行线程唤醒

    在JDK1.5时ReentrantLock的性能比synchronized性能稳定且高的多。synchronized仍有很大的优化空间

    阻塞同步的问题:

    互斥同步的主要问题就是进行线程阻塞和唤醒带来的性能问题。因此这种同步方式被称为阻塞同步,属于悲观的并发策略。无论共享数据是否出现竞争都会进行加锁。**很出现很多不必要的状态切换、维护锁计数器和检查是否有被阻塞的线程需要唤醒等操作。**影响性能

    非阻塞同步

    随着硬件指令集的发展,我们可以使用**基于冲突检测的乐观并发策略。**通俗的说先进先操作,如果没有其他线程争用共享数据,那么操作就成功了,如果有争用产生了冲突,那就进行其他的补偿措施(一般为循环尝试)。这种操作不需要把线程挂起,因此被称为非阻塞同步。

    在这里插入图片描述

    实现方式CAS操作:

    CAS指令由三个操作数:CAS(V,A,B)

    • V:共享变量的内存地址
    • A:旧的预期值
    • B:新的预期值

    在硬件层面保证原子性

    问题:CAS操作的经典问题ABA问题

    在这里插入图片描述

    线程A读取了数据A,线程B将A修改为B后又修改为A,之后线程A再次访问数据A。这样就存在漏洞。大多数情况下ABA不会影响程序并发的争取性。可以为数据添加一个版本号时间戳来标记数据是否被修改过。

    无同步方案

    要保证线程安全不一定要同步。同步只是保障数据争用时的正确性的手段。如果一个方法不涉及共享数据,则无需任何同步措施保证正确性。

    可重入代码:

    可以在代码执行的任何时刻中断它,转而执行另一段代码,而控制权返回后,原来的程序不会出现任何错误。

    线程本地存储:

    如果一段代码中需要的数据必须与其他代码共享,可以试试将这些共享数据的代码放入同一个线程执行。如果可以,则无须同步也能保证线程之间不出现数据争用。

    三、锁优化

    自旋锁与自适应锁

    自旋锁

    由于互斥同步的阻塞对性能影响较大。并且在很多情况下对于共享数据的锁定状态只会持续很短一段时间,为了这段时间去挂起和恢复线程并不值得。所以当物理机可以让两个线程同时执行时,我们可以让请求锁的线程稍等一会并不将其挂起。为了让线程等待,我们只需要让线程执行一个忙循环(自旋),这就是自旋锁。

    自适应锁

    自适应锁就是对自旋锁的自旋次数进行适应性调整。

    如:一个锁对象曾经自旋成功,那么虚拟机认为这次仍然可能成功,进而允许他自旋等待更长的时间。如果一个锁对象自旋很少成功,那么以后获取这个锁时就减少自旋或不自旋。

    锁消除

    锁消除是指在虚拟机即时编译器在运行时发现一些代码上要求同步,但是实际上不可能出现对于共享数据的竞争,就会进行把同步操作进行省略。

    例:

    public String concatstring(String s1,String s2,String s3){
        return s1+s2+s3;
    }
    

    表面上没有锁的存在,实际上jdk会对String连接进行优化,于是以上代码就会变成new StringBuffer().append(s1).append(s2).append(s3).toString();,然而StringBuffer是线程安全的,在其内部就存在锁,但是此时根本无需锁的存在,这里就使用了JVM的锁消除。

    锁粗化

    在编写代码时,推荐将同步块的作用范围限制得尽量小。但是也有例外情况,如果一系列连续的操作都对同一个对象反复加锁和解锁比如在循环体内加锁。那么就需要不停的加锁和释放锁,及时没有线程竞争也会导致性能消耗。这时只需要将锁的作用域扩大到整个循环。只需要加一个锁就可以了。这就是锁粗化

    轻量级锁

    传统的互斥锁属于“重量级”锁。相对应的就是“轻量级”锁。是对“重量级”锁的补充。要理解轻量级锁必须先了解虚拟机的对象的内存布局。HotSpot虚拟机的对象头分为两部分,一部分存储对象自身的运行时数据,一部分存储指向方法区对象类型数据的指针,如果是数组对象的话,还有一部分用于存储数组长度。

    在这里插入图片描述

    Mark Word区域是实现轻量级锁与偏向锁的关键(随着锁标记位的不同,Mark Word的内容不断变化)。

    在这里插入图片描述

    代码进入同步代码块的时候,如果此同步对象没有被锁定,虚拟机首先将在当前线程的栈帧中建立一个名为锁记录(Lock Record)的空间。用于存储当前Mark Word的拷贝,之后尝试CAS操作,成功就修改Mark Word为指向Lock Record的指针并修改锁标记位为00。此时Mark Word内容参考上图。加锁流程图如下:

    在这里插入图片描述

    解锁过程流程图如下:

    在这里插入图片描述

    轻量级锁提升程序性能的依据是“对于绝大部分的锁,在整个同步周期内都不存在竞争”。

    偏向锁

    如果说轻量级锁是在无竞争的情况下使用CAS操作去消除同步使用的互斥量,那么偏向锁就是无竞争的情况下降整个同步都消除掉。

    偏向锁的“偏”是偏心的偏。他的意思是这个锁会偏向于第一个获得他的线程,在接下来的情况如果没有其他的线程要获取他,则持有偏向锁的线程永远不需要同步。而如果有其他的线程要获取这个锁时,偏向模式宣告结束,根据对象是否被锁定恢复到未锁定或轻量级锁定的状态。

    偏向锁优缺点:

    偏向锁可以提高带有同步但是无竞争的程序性能。但是一个共享数据总是被不同的线程访问,那么偏向模式就是多余的。

    展开全文
  • import java.util.Map;... * 如果多个线程操作一个ConcurrentHashMap,put函数内部执行是线程安全的,但是两个put操作的线程安全需要程序员维护。 * */ public class UnSafeTest { static Map map=new Concu
    import java.util.Map;
    import java.util.concurrent.ConcurrentHashMap;
    /**
     * 如果多个线程操作一个ConcurrentHashMap,put函数内部执行是线程安全的,但是两个put操作的线程安全需要程序员维护。
     *
     */
    public class UnSafeTest {
    static Map<String, Long> map=new ConcurrentHashMap<String, Long>();
    public static void main(String[] args) {
    	for(int i=0;i<100000;i++)
    	{
    		Thread t1=new Thread(new ThreadTest());
    		t1.start();
    	}
    }
    }
    class ThreadTest implements Runnable
    {  //两个put中间的get得到的值有可能是1 有可能是2
    	@Override
    	public void run() {
    		// TODO Auto-generated method stub
    		UnSafeTest body1=new UnSafeTest();
    		body1.map.put("1", 1L);
    		try {
    			Thread.sleep((int) (1 + Math.random() * (3 - 1)));//模拟不同的线程执行时间
    		} catch (InterruptedException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
    		Long l1=body1.map.get("1");
    		body1.map.put("1", 2L);
    		Long l2=body1.map.get("1");
    		System.out.println("l1:"+l1+"    l2:"+l2);
    	}	
    }
    
    

    展开全文
  • vector是线程(Thread)同步(Synchronized)的,所以它也是线程安全的,而Arraylist是线程异步(ASynchronized)的,是不安全的。如果不考虑到线程的安全因素,一般用Arraylist效率比较高。 如果集合中的元素的数目...

    转自:https://www.cnblogs.com/zhangzongle/p/5432212.html

    Java中Vector和ArrayList的区别

    首先看这两类都实现List接口,而List接口一共有三个实现类,分别是ArrayList、Vector和LinkedList。List用于存放多个元素,能够维护元素的次序,并且允许元素的重复。3个具体实现类的相关区别如下:

    1. ArrayList是最常用的List实现类,内部是通过数组实现的,它允许对元素进行快速随机访问。数组的缺点是每个元素之间不能有间隔,当数组大小不满足时需要增加存储能力,就要讲已经有数组的数据复制到新的存储空间中。当从ArrayList的中间位置插入或者删除元素时,需要对数组进行复制、移动、代价比较高。因此,它适合随机查找和遍历,不适合插入和删除。
    2. Vector与ArrayList一样,也是通过数组实现的,不同的是它支持线程的同步,即某一时刻只有一个线程能够写Vector,避免多线程同时写而引起的不一致性,但实现同步需要很高的花费,因此,访问它比访问ArrayList慢。
    3. LinkedList是用链表结构存储数据的,很适合数据的动态插入和删除,随机访问和遍历速度比较慢。另外,他还提供了List接口中没有定义的方法,专门用于操作表头和表尾元素,可以当作堆栈、队列和双向队列使用。
    4. vector是线程(Thread)同步(Synchronized)的,所以它也是线程安全的,而Arraylist是线程异步(ASynchronized)的,是不安全的。如果不考虑到线程的安全因素,一般用Arraylist效率比较高。
    5. 如果集合中的元素的数目大于目前集合数组的长度时,vector增长率为目前数组长度的100%,而arraylist增长率为目前数组长度
      的50%.如过在集合中使用数据量比较大的数据,用vector有一定的优势。

    6. 如果查找一个指定位置的数据,vector和arraylist使用的时间是相同的,都是0(1),这个时候使用vector和arraylist都可以。而
      如果移动一个指定位置的数据花费的时间为0(n-i)n为总长度,这个时候就应该考虑到使用Linkedlist,因为它移动一个指定位置的数据
      所花费的时间为0(1),而查询一个指定位置的数据时花费的时间为0(i)。
      ArrayList 和Vector是采用数组方式存储数据,此数组元素数大于实际存储的数据以便增加和插入元素,
      都允许直接序号索引元素,但是插入数据要设计到数组元素移动 等内存操作,所以索引数据快插入数据慢,
      Vector由于使用了synchronized方法(线程安全)所以性能上比ArrayList要差
      ,LinkedList使用双向链表实现存储,按序号索引数据需要进行向前或向后遍历,但是插入数据时只需要记录本项的前后项即可,所以插入数度较快!

    7. 笼统来说:LinkedList:增删改快
                    ArrayList:查询快(有索引的存在)

    关于Vector,真是有点坑啊,阿里我尝试去面试,那位面试官问我,Vector你说是线程安全的,那是怎么实现安全的

    我回答:他的方法里很多都用了synchronized关键字啊,实现了同步

    他又问我,那Vector还有其他手段实现了同步么?我当时想,源码里没别的复杂的东西了,就是靠这个关键字搞得

    难不成是我没看到,眼瞎了?有知道的告诉我下啊,(那个modcount不是,就不用跟我说了)

    Vector还真不算是线程安全,https://blog.csdn.net/zlp1992/article/details/50433778这里就很详细的展示了什么叫

    实力坑爹:

    先看段代码:

        private static Vector<Integer> vector=new Vector();
    
        public static void main(String[] args) {
            while(true){
                for(int i=0;i<10;i++){
                    vector.add(i); //往vector中添加元素
                }
                Thread removeThread=new Thread(new Runnable() {         
                    @Override
                    public void run() {
                        //获取vector的大小
                        for(int i=0;i<vector.size();i++){
                            //当前线程让出CPU,使例子中的错误更快出现
                            Thread.yield();
                            //移除第i个数据
                            vector.remove(i);
                        }
                    }
                });
                Thread printThread=new Thread(new Runnable() {          
                    @Override
                    public void run() {
                        //获取vector的大小
                        for(int i=0;i<vector.size();i++){
                            //当前线程让出CPU,使例子中的错误更快出现
                            Thread.yield();
                            //获取第i个数据并打印
                            System.out.println(vector.get(i));
                        }
                    }
                });         
                removeThread.start();
                printThread.start();
                //避免同时产生过多线程
                while(Thread.activeCount()>20);
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38

    运行之后,会有如下异常:

    4
    6
    6
    1
    8
    3
    5
    Exception in thread "Thread-285" java.lang.ArrayIndexOutOfBoundsException: Array index out of range: 11
        at java.util.Vector.get(Unknown Source)
        at VectorTest$2.run(VectorTest.java:31)
        at java.lang.Thread.run(Unknown Source)
    7
    9
    0
    6
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    这表明上述代码在使用Vector的时候线程并不是安全的,使用get访问Vector时出现了越界。这是为什么呢? 
    Vector类中对get以及remove,size方法都加了synchronized关键字来保证同步,也就说当一个线程调用了这些方法时,其他线程不能再同时调用这些方法。换言之,不能出现两个及两个以上的线程在同时调用这些同步方法。 
    那么为什么例子中会出现问题呢?这是因为 例子中有些线程连续调用了两个或两个以上的同步方法。 
    例子中 removeThread线程先调用了vector.size()方法获得vector的大小,接着调用vector.remove(i)移除第i个元素;而printThread线程也先调用vector.size()方法获得vector的大小,接着调用vector.get()获得第i个元素。

    假设此时vector大小为5,此时printThread线程执行到 i=4 ,进入for循环但在 System.out.println(vector.get(i));之前 printThread线程的CPU时间片已到,线程printThread转入就绪状态; 
    此时removeThread线程获得CPU开始执行,把vector的5个元素全删除了,这是removeThreadCPU时间片已到; 
    接着printThread获得CPU进行执行,由于之前printThread中的i==4,于是调用vector.get(4)获取元素,此时由于vector中的元素已被removeThread线程全部删除,因此报错。

    总的来说,vector保证了其同步方法不能被两个及两个以上线程同时访问,但是我们自己的操作会使得即使使用了Vector线程也不安全,如果不大清楚,最好自己加上 synchronized进行同步吧。

    以上是copy人家的实验,充分展示了Vector不靠谱的一点,所以即便是应用java封装好的所谓的线程安全的类,也要自己好好

    思考一下,小心被坑。。。。

    展开全文
  • java中哪些类是线程安全

    千次阅读 2022-02-25 21:26:21
    如果一个类被设计为允许多线程正确访问,我们就说这个类就是“线程安全”的(thread-safe),上面的Counter类就是线程安全的。Java标准库的java.lang.StringBuffer也是线程安全的。 还有一些不变类,例如String,...
  • Vector并非是绝对线程安全

    千次阅读 2018-07-18 17:36:58
    众所周知,Vector是一个线程安全的类,其在add()等操作上添加了synchronized关键字实现同步,但是并非是绝对线程安全类. 当进行迭代遍历时,如果在另一个线程执行add(),remove()操作,仍然会有机率抛出异常...
  • 单例模式 单例模式是 Java 中常用的设计模式...实现线程安全的单例模式有以下几种方式: 1.饿汉式 public class Singleton { private static Singleton instance = new Singleton(); private Singleton() { }
  • 1.2 绝对线程安全 1.3 相对线程安全 1.4 线程兼容 1.5 线程对立 1.6 线程安全的实现方法 1.6.1 互斥同步 线程执行互斥代码的过程 ① 实现互斥同步的方法--synchronized关键字 ② 实现互斥同步的方法--...
  • ConcurrentHashMap 能否保证绝对线程安全

    万次阅读 多人点赞 2020-02-29 20:04:11
    ConcurrentHashMap 是 Java 并发包中提供的一个线程安全且高效的 HashMap 实现,以弥补 HashMap 不适合在并发环境中操作使用的不足,本文就来分析下 Co...
  • shared_ptr的线程安全

    千次阅读 2019-08-22 23:52:14
    shared_ptr的线程安全性 shared_ptr的reference count是线程安全的,但是指向的对象不是线程安全的! 本文链接:https://blog.csdn.net/D_Guco/article/details/80155323 shared_ptr的出现在某种程度上...
  • 上一篇:IT界惊现文豪!华为领导及阿里P10遭吐槽一、线程安全等级之前的博客中已有所提及“线程安全”问题,一般我们常说某某类是线程安全的,某某是非线程安全的。其实线程安全并不是一个“非黑即...
  • 大话线程安全线程安全的实现方式

    多人点赞 热门讨论 2021-04-26 09:01:02
    什么是线程安全 一个类可以被多个线程安全调用那么这个类就是线程安全的。 根据线程共享数据的安全程度可以分为以下五类线程安全: 不可变 绝对线程安全 相对线程安全 线程兼容 线程对立 ...
  • 之前在看一些模拟面试的视频时,面试官问到:“List如何保证线程...这个问题其实可以从《深入理解Java虚拟机》这本书中找到答案绝对线程安全绝对的线程安全能够完全满足Brian Goetz给出的线程安全的定义,这个定义其...
  • Android 线程与线程安全

    千次阅读 2021-11-08 19:30:18
    1.线程 线程是进程中可独立执行的最小单位,也是CPU资源分配的基本单位; 进程是程序向操作系统申请资源的基本条件,一个进程可以包含多个线程,同一个进程中的线程可以共享进程中的资源,如内存空间和文件句柄; 操作...
  • JAVA多线程-线程安全问题

    千次阅读 2022-01-24 19:17:29
    但是 synchronized是一个很重的操作 三、线程安全的实现方法 3.1、数据不可变 在Java当中,一切不可变的对象(immutable)一定是线程安全的,无论是对象的方法实现还是方法的调用者,都不需要再进行任何线程安全保障...
  • 多线程情况下如何保证线程安全

    千次阅读 2020-05-01 15:50:18
    按照“线程安全”的安全程度由强到弱来排序,我们可以将java语言中各种操作共享的数据分为以下5类:不可变、绝对线程安全、相对线程安全、线程兼容和线程对立。 1、不可变 在java语言中,不可变的对象一定是线程...
  • 线程重用导致用户信息错乱 生产环境中,有时获取到的用户信息是别人的。查看代码后,发现是使用了ThreadLocal缓存获取到的用户信息。 ThreadLocal适用于变量在线程间隔离,而在方法或类间共享的场景。 若用户信息的...
  • Java中Map线程安全实现

    2021-03-18 12:04:08
    前言介绍:volatile和transient关键字第一种实现:HashTable第二种实现:Collections.synchronizedMap(map)第三种实现:...JVM会把该线程对应的本地内存私有拷贝变化强制刷新到主内存中去,并且会其...
  • 线程安全的list该如何实现?

    千次阅读 2021-03-01 11:12:28
    List集合相信大家都经常用吧,但是可惜的是它不是线程安全的,那么,该如何把list变成一个线程安全的集合呢?下面就来看看吧。首先我们知道,ArrayList不是一个线程安全的集合,因此在实现多线程开发时,我们不能够...
  • 线程安全的定义:当多个线程...Java语言中的线程安全按照线程安全的“安全程度”由强至弱来排序,可以将Java中各种操作共享的数据分为5类:不可变、绝对线程安全、相对线程安全、线程兼容和线程对立。不可变不可变(Im
  • 也就是要注意:atomic所说的线程安全只是保证了getter和setter存取方法的线程安全,并不能保证整个对象是线程安全的。如下列所示:比如:@property(atomic,strong)NSMutableArray *arr; 如果一个线程循环的读...
  • JAVA-线程安全与锁机制详解

    千次阅读 2018-10-06 16:00:09
    不可变,绝对线程安全,相对线程安全,线程兼容和线程对立 不可变 只要一个不可变的对象被正确的构建出来,没有发生this引用逃逸,那其外部的可见状态永远不会改变,例如final修饰的对象,JAVA API中常见的有...
  • 1.1 线程安全的定义 我们可以看下《Java并发编程实战》在2.1章节中的定义: 当多个线程访问某个类时,这个类始终都能表现出正确的行为,那么就称这个类是线程安全的。 我们常用synchronized或者Lock来实现线程安全的...
  • ConcurrentHashMap并不是绝对线程安全

    千次阅读 2011-11-09 11:19:49
    ConcurrentHashMap是线程安全的概念已经深入人心,让我们在使用的时候有些大意了,我也懒得动脑子,直接使用,结果碰到钉子了. 这个问题让我很郁闷,程序逻辑全是对的,但是问题却明明摆在那边,最后怀疑是HashMap...
  • 【多线程】如何保证线程安全

    万次阅读 多人点赞 2018-03-15 10:19:14
    按照“线程安全”的安全程度由强到弱来排序,我们可以将java语言中各种操作共享的数据分为以下5类:不可变、绝对线程安全、相对线程安全、线程兼容和线程对立。 1、不可变 在java语言中,不可变的对象一定...
  • Java并发:线程安全与锁优化

    千次阅读 2018-01-01 18:25:15
    概述人们很难想象现实中的对象在一项工作进行期间,会被不停地中断和切换,对象的属性(数据)可能会在中断期间被修改和变“脏”,而这些事情在计算机世界中则是很正常的事情。...1.线程安全《Java Co...
  • Java语言中各种操作共享的数据有5种类型:不可变、绝对线程安全、相对线程安全、线程兼容、线程独立 ① 不可变 不可变(Immutable) 的对象一定是线程安全的,不需要再采取任何的线程安全保障措施。 只要能...
  • 序言:想用好多线程,只知道多线程是如何工作的还是不够,更多的我们应该知道如何多线程如何实现 “线程安全线程安全定义: 代码封装了所有必要的正确性保障手段(如互斥同步等),令调用者无需关心多线程问题...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 100,578
精华内容 40,231
关键字:

绝对线程安全