精华内容
下载资源
问答
  • java 线程安全是什么意思

    千次阅读 2017-11-13 15:27:37
    java 线程安全是什么意思?ArrayList和Vector有什么区别?HashMap和HashTable有什么区别?StringBuilder和StringBuffer有什么区别?这些都是Java面试中常见的基础问题。面对这样的问题,回答是:ArrayList是非线程...

    java 线程安全是什么意思?ArrayList和Vector有什么区别?HashMap和HashTable有什么区别?StringBuilder和StringBuffer有什么区别?这些都是Java面试中常见的基础问题。面对这样的问题,回答是:ArrayList是非线程安全的,Vector是线程安全的;HashMap是非线程安全的,HashTable是线程安全的;StringBuilder是非线程安全的,StringBuffer是线程安全的。因为这是昨晚刚背的《Java面试题大全》上面写的。此时如果继续问:什么是线程安全?线程安全和非线程安全有什么区别?分别在什么情况下使用?这样一连串的问题,一口老血就喷出来了…


    非线程安全的现象模拟

    这里就使用ArrayList和Vector二者来说明。

    下面的代码,在主线程中new了一个非线程安全的ArrayList,然后开1000个线程分别向这个ArrayList里面添加元素,每个线程添加100个元素,等所有线程执行完成后,这个ArrayList的size应该是多少?应该是100000个?

    [java] view plain copy
    1. public class Main  
    2. {  
    3.     public static void main(String[] args)  
    4.     {  
    5.         // 进行10次测试  
    6.         for(int i = 0; i < 10; i++)  
    7.         {  
    8.             test();  
    9.         }  
    10.     }  
    11.       
    12.     public static void test()  
    13.     {  
    14.         // 用来测试的List  
    15.         List<Object> list = new ArrayList<Object>();  
    16.           
    17.         // 线程数量(1000)  
    18.         int threadCount = 1000;  
    19.           
    20.         // 用来让主线程等待threadCount个子线程执行完毕  
    21.         CountDownLatch countDownLatch = new CountDownLatch(threadCount);  
    22.           
    23.         // 启动threadCount个子线程  
    24.         for(int i = 0; i < threadCount; i++)  
    25.         {  
    26.             Thread thread = new Thread(new MyThread(list, countDownLatch));  
    27.             thread.start();  
    28.         }  
    29.           
    30.         try  
    31.         {  
    32.             // 主线程等待所有子线程执行完成,再向下执行  
    33.             countDownLatch.await();  
    34.         }  
    35.         catch (InterruptedException e)  
    36.         {  
    37.             e.printStackTrace();  
    38.         }  
    39.           
    40.         // List的size  
    41.         System.out.println(list.size());  
    42.     }  
    43. }  
    44.   
    45. class MyThread implements Runnable  
    46. {  
    47.     private List<Object> list;  
    48.       
    49.     private CountDownLatch countDownLatch;  
    50.       
    51.     public MyThread(List<Object> list, CountDownLatch countDownLatch)  
    52.     {  
    53.         this.list = list;  
    54.         this.countDownLatch = countDownLatch;  
    55.     }  
    56.       
    57.     public void run()  
    58.     {  
    59.         // 每个线程向List中添加100个元素  
    60.         for(int i = 0; i < 100; i++)  
    61.         {  
    62.             list.add(new Object());  
    63.         }  
    64.           
    65.         // 完成一个子线程  
    66.         countDownLatch.countDown();  
    67.     }  
    68. }  

    上面进行了10次测试(为什么要测试10次?因为非线程安全并不是每次都会导致问题)。

    输出结果:

    99946

    100000

    100000

    100000

    99998

    99959

    100000

    99975

    100000

    99996


    上面的输出结果发现,并不是每次测试结果都是100000,有好几次测试最后ArrayList的size小于100000,甚至时不时会抛出个IndexOutOfBoundsException异常。(如果没有这个现象可以多试几次)

    这就是非线程安全带来的问题了。上面的代码如果用于生产环境,就会有隐患就会有BUG了。


    再用线程安全的Vector来进行测试,上面代码改变一处,test()方法中

    [java] view plain copy
    1. List<Object> list = new ArrayList<Object>();  
    改成

    [java] view plain copy
    1. List<Object> list = new Vector<Object>();  

    再运行程序。


    输出结果:

    100000

    100000

    100000

    100000

    100000

    100000

    100000

    100000

    100000

    100000


    再多跑几次,发现都是100000,没有任何问题。因为Vector是线程安全的,在多线程操作同一个Vector对象时,不会有任何问题。

    再换成LinkedList试试,同样还会出现ArrayList类似的问题,因为LinkedList也是非线程安全的。


    二者如何取舍

    非线程安全是指多线程操作同一个对象可能会出现问题。而线程安全则是多线程操作同一个对象不会有问题。

    线程安全必须要使用很多synchronized关键字来同步控制,所以必然会导致性能的降低

    所以在使用的时候,如果是多个线程操作同一个对象,那么使用线程安全的Vector;否则,就使用效率更高的ArrayList。


    非线程安全!=不安全

    有人在使用过程中有一个不正确的观点:我的程序是多线程的,不能使用ArrayList要使用Vector,这样才安全。

    非线程安全并不是多线程环境下就不能使用。注意我上面有说到:多线程操作同一个对象。注意是同一个对象。比如最上面那个模拟,就是在主线程中new的一个ArrayList然后多个线程操作同一个ArrayList对象。

    如果是每个线程中new一个ArrayList,而这个ArrayList只在这一个线程中使用,那么肯定是没问题的。


    线程安全的实现

    线程安全是通过线程同步控制来实现的,也就是synchronized关键字。   

    在这里,我用代码分别实现了一个非线程安全的计数器和线程安全的计数器Counter,并对他们分别进行了多线程测试。


    非线程安全的计数器:

    [java] view plain copy
    1. public class Main  
    2. {  
    3.     public static void main(String[] args)  
    4.     {  
    5.         // 进行10次测试  
    6.         for(int i = 0; i < 10; i++)  
    7.         {  
    8.             test();  
    9.         }  
    10.     }  
    11.       
    12.     public static void test()  
    13.     {  
    14.         // 计数器  
    15.         Counter counter = new Counter();  
    16.           
    17.         // 线程数量(1000)  
    18.         int threadCount = 1000;  
    19.           
    20.         // 用来让主线程等待threadCount个子线程执行完毕  
    21.         CountDownLatch countDownLatch = new CountDownLatch(threadCount);  
    22.           
    23.         // 启动threadCount个子线程  
    24.         for(int i = 0; i < threadCount; i++)  
    25.         {  
    26.             Thread thread = new Thread(new MyThread(counter, countDownLatch));  
    27.             thread.start();  
    28.         }  
    29.           
    30.         try  
    31.         {  
    32.             // 主线程等待所有子线程执行完成,再向下执行  
    33.             countDownLatch.await();  
    34.         }  
    35.         catch (InterruptedException e)  
    36.         {  
    37.             e.printStackTrace();  
    38.         }  
    39.           
    40.         // 计数器的值  
    41.         System.out.println(counter.getCount());  
    42.     }  
    43. }  
    44.   
    45. class MyThread implements Runnable  
    46. {  
    47.     private Counter counter;  
    48.       
    49.     private CountDownLatch countDownLatch;  
    50.       
    51.     public MyThread(Counter counter, CountDownLatch countDownLatch)  
    52.     {  
    53.         this.counter = counter;  
    54.         this.countDownLatch = countDownLatch;  
    55.     }  
    56.       
    57.     public void run()  
    58.     {  
    59.         // 每个线程向Counter中进行10000次累加  
    60.         for(int i = 0; i < 10000; i++)  
    61.         {  
    62.             counter.addCount();  
    63.         }  
    64.           
    65.         // 完成一个子线程  
    66.         countDownLatch.countDown();  
    67.     }  
    68. }  
    69.   
    70. class Counter  
    71. {  
    72.     private int count = 0;  
    73.   
    74.     public int getCount()  
    75.     {  
    76.         return count;  
    77.     }  
    78.   
    79.     public void addCount()  
    80.     {  
    81.         count++;  
    82.     }  
    83. }  

    上面的测试代码中,开启1000个线程,每个线程对计数器进行10000次累加,最终输出结果应该是10000000。

    但是上面代码中的Counter未进行同步控制,所以非线程安全。

    输出结果:

    9963727

    9973178

    9999577

    9987650

    9988734

    9988665

    9987820

    9990847

    9992305

    9972233


    稍加修改,把Counter改成线程安全的计数器:

    [java] view plain copy
    1. class Counter  
    2. {  
    3.     private int count = 0;  
    4.   
    5.     public int getCount()  
    6.     {  
    7.         return count;  
    8.     }  
    9.   
    10.     public synchronized void addCount()  
    11.     {  
    12.         count++;  
    13.     }  
    14. }  

    上面只是在addCount()方法中加上了synchronized同步控制,就成为一个线程安全的计数器了。再执行程序。

    输出结果:

    10000000

    10000000

    10000000

    10000000

    10000000

    10000000

    10000000

    10000000

    10000000

    10000000


    转载自:http://blog.csdn.net/xiao__gui/article/details/8934832

    展开全文
  • 线程安全就是多线程访问时,采用了加锁机制,当一个线程访问该类的某个数据时,进行保护,其他线程不能进行访问直到该线程读取完,其他线程才可使用。不会出现数据不一致或者数据污染。 线程不安全就是不提供数据...

    题目分析:作者正在学习中…

    【答案】

    • 线程安全就是多线程访问时,采用了加锁机制,当一个线程访问该类的某个数据时,进行保护,其他线程不能进行访问直到该线程读取完,其他线程才可使用。不会出现数据不一致或者数据污染
    • 线程不安全就是提供数据访问保护,有可能出现多个线程先后更改数据造成所得到的数据是脏数据

    参考文章传送门: link.

    【题目拓展】

    • 什么情况下会造成线程的不安全?
      一是存在共享数据(也称临界资源),二是存在多条线程共同操作共享数据
    • 什么是线程,它与进程又有什么关系?
      答: link.
    • 什么是脏数据
      答:一个事物读取了另一个事物未提交的数据(常常是并发操作引起的,并发操作所带来了一致性问题包括:丢失的修改,不可重复读,读“脏”数据,幻读)。
    • 关于线程安全的其他结论
      答: ArrayList是非线程安全的,Vector是线程安全的;
      HashMap是非线程安全的,HashTable是线程安全的;
      StringBuilder是非线程安全的,StringBuffer是线程安全的。
    展开全文
  • 线程和进程最大的根本区别就是内存数据的共享。每个进程都独享一个虚拟内存[虚拟内存 = 物理内存 + SWAP/页面文件)]。一个进程可以拥有多个线程,一般来说一个线程仅独享一个进程的虚拟内存中的一个函数栈帧。程序...

    线程和进程最大的根本区别就是内存数据的共享。

    每个进程都独享一个虚拟内存[虚拟内存 = 物理内存 + SWAP/页面文件)]。

    一个进程可以拥有多个线程,一般来说一个线程仅独享一个进程的虚拟内存中的一个函数栈帧。

    程序储存数据有下面几种常用的方式:

    自动变量: 自动变量是储存在栈中的,随着函数的调用而产生,结束而销毁。

    静态(全局)变量: 静态分配的变量是随着程序的运行产生,程序的结束而销毁,这些变量储存在内存一个专门存放静态变量的区域。

    堆: 即通过malloc()申请的内存,一旦申请后,直到调用free(),或程序结束后才释放。

    其中造成“非线程安全”的主要是静态变量以及堆。

    自动变量仅存在于函数自己的栈中,不管你如何修改其值,均不会影响其他函数(准确来说是线程)的数据。

    静态变量独立储存于一个区域,这就意味着一个静态变量由整个进程的所有线程共享,一个线程修改了静态变量的值,将会改变其他线程读对该变量取得的结果,储存于堆的数据亦如此。

    所谓“线程安全”,即采取了的措施,避免不同的线程同时对一个变量进行修改。

    例如某些函数的结果保存于静态分配的变量,或者是保存于堆中的一个区域,可以选择通过加锁,或互斥量来阻塞其他线程对这些函数的调用,但细心的话你也看到了“阻塞”二字,因此最佳的办法就是避免采用这些用到静态分配或堆的函数。

    如果你用过PHP的Pthreads模块,并且理解了本文,那你应该明白为何Pthreads模块强制要求使用线程安全版本的PHP。

    展开全文
  • 一、线程安全是什么意思 As Seth stated thread safe means that a method or class instance can be used by multiple threads at the same time without any problems occuring. Consider the following ...

    一、线程安全是什么意思

    As Seth stated thread safe means that a method or class instance can be used by multiple threads at the same time without any problems occuring.

    Consider the following method:

    private int myInt = 0;public int AddOne(){
        int tmp = myInt;
        tmp = tmp + 1;
        myInt = tmp;
        return tmp;}

    Now thread A and thread B both would like to execute AddOne(). but A starts first and reads the value of myInt (0) into tmp. Now for some reason the scheduler decides to halt thread A and defer execution to thread B. Thread B now also reads the value of myInt (still 0) into it's own variable tmp. Thread B finishes the entire method, so in the end myInt = 1. And 1 is returned. Now it's Thread A's turn again. Thread A continues. And adds 1 to tmp (tmp was 0 for thread A). And then saves this value in myInt. myInt is again 1.

    So in this case the method AddOne was called two times, but because the method was not implemented in a thread safe way the value of myInt is not 2, as expected, but 1 because the second thread read the variable myInt before the first thread finished updating it.

    Creating thread safe methods is very hard in non trivial cases. And there are quite a few techniques. In Java you can mark a method as synchronized, this means that only one thread can execute that method at a given time. The other threads wait in line. This makes a method thread safe, but if there is a lot of work to be done in a method, then this wastes a lot of space. Another technique is to 'mark only a small part of a method as synchronized' by creating a lock or semaphore, and locking this small part (usually called the critical section). There are even some methods that are implemented as lockless thread safe, which means that they are built in such a way that multiple threads can race through them at the same time without ever causing problems, this can be the case when a method only executes one atomic call. Atomic calls are calls that can't be interrupted and can only be done by one thread at a time.

    二、线程安全与同步锁有啥区别呢

    同步锁只是一种达到线程安全的方法。

    Thread safe doesn't related with synchronization of data access. It is only related with multiple threads can modify collection at the same time


    The synchronized keyword is one way of restricting access to a method or block of code so that otherwise thread-unsafe data doesn't get corrupted. This keyword protects the method or block by requiring that a thread has to acquire exclusive access to a certain lock before it can enter the method or block, while providing memory visibility so that threads don't see stale data.


    how about "synchronization is a mechanism for making code thread-safe, but not all thread-safe code uses synchronization".

    转载于:https://my.oschina.net/u/2308739/blog/608010

    展开全文
  • java中的线程安全是什么: 就是线程同步的意思,就是当一个程序对一个线程安全的方法或者语句进行访问的时候,其他的不能再对他进行操作了,必须等到这次访问结束以后才能对这个线程安全的方法进行访问。 什么叫线程...
  • RefCountedThreadSafe的引用计数是原子操作的,所以网上查到的统一的说法线程安全,RefCountedThreadSafe也有很多非原子操作,它所谓的线程安全是什么意思 比如用scoped_refptr操作RefCountedThreadSafe跨线程会...
  • java线程安全是什么

    2021-01-20 13:45:27
    java中的线程安全是什么: 就是线程同步的意思,就是当一个程序对一个线程安全的方法或者语句进行访问的时候,其他的不能再对他进行操作了,必须等到这次访问结束以后才能对这个线程安全的方法进行访问 什么叫线程...
  • 线程安全十万个为什么 问:平时项目中使用锁和synchronized比较多,而很少使用volatile,难道就没有保证可见性? 答:锁和synchronized即可以保证原子性,也可以保证可见性。都通过保证同一时间只有一个线程...
  • 什么是线程安全

    千次阅读 2019-01-06 21:11:21
    java中的线程安全是什么:  就是线程同步的意思,就是当一个程序对一个线程安全的方法或者语句进行访问的时候,其他的不能再对他进行操作了,必须等到这次访问结束以后才能对这个线程安全的方法进行访问 什么叫线程...
  • 1.可以这样理解,加锁的就是安全的,不加锁的就是不安全的(感觉比较生动,不知道对不对,望指出)线程安全 就是多线程访问时,采用了加锁机制,当一个线程访问该类的某个数据时,进行保护,其他...到底是什么意思呢?
  • 线程安全,多线程,同步,异步这些概念都是什么意思例如:arraylist ,linkedlist, vector 说他们哪些是线程安全的,这个是什么意思线程安全和效率有什么联系?特别是面试的时候总是问collection set map 区别,...
  • 什么线程安全

    2019-10-12 10:06:15
    就是线程同步的意思,就是当一个程序对一个线程安全的方法或者语句进行访问的时候,其他的不能再对他进行操作了,必须等到这次访问结束以后才能对这个线程安全的方法进行访问 什么线程安全: 如果你的代码所在的...
  • 就是线程同步的意思,就是当一个程序对一个线程安全的方法或者语句进行访问的时候,其他的不能再对他进行操作了,必须等到这次访问结束以后才能对这个线程安全的方法进行访问 什么线程安全: 如果你的代码所在的...
  • 网上有这种说法:[color=#3366FF]AWT 组件是 “线程安全...AWT 组件是 “线程安全的(thread-safe)”,是什么意思,不需要使用java.awt.EventQueue.invokeLater()?那为什么设计上java.awt.EventQueue.invokeLater()?
  • ArrayList为什么是线程安全

    千次阅读 2019-09-06 20:40:41
    提到线程安全我们应该第一时间想到锁机制,当一个线程访问该类的某个数据时,进行保护,其他... 从源码的角度来看,因为vector的方法前加了,synchronized 关键字,也就是同步的意思,sun公司希望vector是线程安全的...
  • (3) 非阻塞IO - IO多路复用(IO 多路复用是什么意思?) IO多路复用中有三种方式:select,poll,epoll。需要注意的是,select,poll是线程不安全的,epoll是线程安全的 redis内部实现采用epoll,采用了epoll+自己...
  • 线程安全

    2017-09-28 08:16:32
    什么是线程安全?我们用《java concurrency in practice 》中的一句话来表述:当多个线程访问一个对象时,如果不用考虑这些线程在运行时环境下的调度和...线程安全是和对象密切绑定的;2.线程的安全性是由于线程调...
  • java中的线程安全是什么: 就是线程同步的意思,就是当一个程序对一个线程安全的方法或者语句进行访问的时候,其他的不能再对他进行操作了,必须等到这次访问结束以后才能对这个线程安全的方法进行访问 什么叫线程...
  • 1.可以这样理解,加锁的就是安全的,不加锁的就是不安全的(感觉比较生动,不知道对不对,望指出)线程安全 就是多线程访问时,采用了加锁机制,当一个线程访问该类的某个数据时,进行保护,...到底是什么意思呢?如...
  • 首先说一下什么是线程不安全:线程安全就是多线程访问时,采用了加锁机制,当一个线程访问该类的某个数据时,进行保护,其他线程不能进行访问直到该线程读取完,其他线程才可使用。不会出现数据不一致或者数据污染。...

空空如也

空空如也

1 2 3 4 5 ... 15
收藏数 291
精华内容 116
关键字:

线程安全是什么意思