什么是线程安全
当多个线程访问某个类时,不管运行时环境采用何种调度方式或者这些线程将如何交替执行,并且在调用代码中不需要任何额外的同步或者协同,这个类都能表现出正确的行为,那么就称这个类是线程安全的。
线程封闭的三种方式
1、ad-hoc;
2、栈封闭;
3、ThreadLocal
当不是自己的类时如何安全的发布一个类
1、委托给线程安全的类来做;2、仿造Collections对容器的包装,将内部成员对象进行线程安全包装。
Serlvet不是线程安全的
1、因为使用时没有共享的需求;2、当tomcat收到请求到最后应答出去都是由一个线程来负责的。
死锁
两个或两个以上的进程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁。
多个操作者(m>=2)争夺多个资源(N>=2)(m>=2)并且争夺锁的顺序不对。
写一段简单死锁的代码
一个方法实现是先获取第一把锁,在获取第二把锁,而另一个方法是先获取第二把锁,再获取第一把锁。分别用两个线程执行这两个方法就会造成死锁。
动态死锁
例子:银行转钱,张三给李四转钱,李四给张三转钱会出现死锁。解决第一种方式:根据传入两个值的hash比较来获得锁。第二种方式:使用传入参数里面的自定义锁来尝试获得锁(tryLock)来解决(容易产生活锁的情况)。
活锁
两个线程在尝试拿锁的机制中,发生多个线程之间互相谦让,不断发生同一个线程总是拿到同一把锁,在尝试拿另一把锁时因为拿不到,而将本来已经持有的锁释放的过程。解决办法:每个线程休眠随机数,错开拿锁的时间。
使用线程安全的单例模式创建的方式
1、懒汉式的双重检查(基本已经不使用了);2、懒汉式的延迟初始化加载模式;3、饿汉式
并发实际使用小技巧
为了防止多线程对同一个任务重复执行,在实现多线程功能时的小技巧,使用新创建一个FutureTask,然后向conCurrentHashMap中放,如果能放不进去说明当前线程成功抢位了,在执行当前线程的任务。