1.什么是线程安全?
如果说某个集合是线程安全的,那么我们就不用考虑并发访问这个集合?(需要定义自己百度,但是很难懂)
2.深入jvm中的线程安全的级别。
a不变模式(String等基本类型)
b、绝对线程安全(无论咋样处理都安全,把各种方法各种组合使用也安全。)
c.相对线程安全(就是那些集合了,都是每个同步方法单独是安全的)
3.来点实惠的例子(arraylist线程不安全)
package 线程安全的讨论; import java.util.ArrayList; class MyThread implements Runnable { private ArrayList<Integer> arry=null; public MyThread (ArrayList<Integer> arry) { this.arry=arry; } @Override public void run() { // TODO Auto-generated method stub for(int i=0;i<10;i++) { arry.add(10); } System.out.println(arry.size()); } } public class ArrayListTest { public static void main(String[] args) { // TODO Auto-generated method stub ArrayList<Integer> arry=new ArrayList<Integer>(); for(int i=0;i<100;i++) { new Thread(new MyThread(arry)).start(); } } }
很简单的逻辑,共100个线程,每个添加10个数,最后那个size应该是多少呢?1000,恭喜你,都学会算数了,你自己执行以下看看。
把大象添加到冰箱共需要多少步?
arry.add()需要两步。1.放到尾巴2,size+1 两个线程读到相同的尾巴呢,一个丢失就更新了(跟数据库中的丢失更新是一样一样的);
2.vector不是绝对安全的
package 线程安全的讨论; import java.util.Vector; class A implements Runnable { private Vector<Integer> a=null; public A(Vector<Integer> a) { this.a=a; } @Override public void run() { // TODO Auto-generated method stub int count=0; while(count<10) { a.add(10); try { Thread.sleep((long) (3000*Math.random())); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println(a.size()); count++; } } } public class VectorTest { public static void main(String[] args) { // TODO Auto-generated method stub Vector<Integer> vec=new Vector<Integer>(); for(int i=0;i<2;i++) { new Thread(new A(vec)).start();; } } }
运行之后会有相同的大小,为啥呢?size和add都是线程安全,但是两者合起来就不是线程安全的,如果加synchornized{add,size};就对了。这样就是绝对线程安全。