文档

java体系技术文档


线程安全

<h2>什么是线程安全?</h2> <ul> <li>线程安全实质上是指内存的安全;</li> <li>jvm中的内存数据可以线程私有的和线程共享的,线程私有的就无所谓线程安全,因为它们是线程独占的,不存在线程安全问题;</li> <li>所以线程安全是指,线程共享的数据由于可以被任何线程访问到,在没有限制的情况下存在被其它线程意外修改的风险(多线程情况下)。</li> </ul> <h2>如何解决线程安全问题?</h2> <p>解决问题的过程其实就是一个取舍的过程,不同的解决方案有不同的侧重点。</p> <ul> <li>线程私有的东西不让别人知道;比如栈、程序计数器中的数据,是单独给线程分配的(局部变量),其它线程无权访问,这是由操作系统报障的。</li> <li>大家不要抢,人人有份;上面方式的数据只有只有自己可以访问到,但是有些数据必须是要让所有的线程能访问到;这样就不能在是局部变量,而要变成全局变量;ThreadLocal就提供了这样一种机制(每个线程都拷贝一份,互不影响),人人有份。</li> <li>只能看,不能摸;线程共享的变量规定只能读取,不能修改;其实就是常量或只读变量,它们对于多线程是安全的,想改也改不了。</li> <li>先入为主,先到先得;公共区域的数据,要被多个线程操作时,为了确保数据的安全(或一致)性,需要给数据加一把锁(互斥锁),要想操作数据,先获取锁再说吧。</li> <li>相信不会发生线程安全问题;即使数据在共享区,当前环境有100个线程和有2个线程的情况下,发生线程安全问题的概率还是大大不一样的;如果是线程特别少的情况下,这时候我们就需要使用CAS技术了,先相信不会发生线程安全问题,不加锁(因为所的获取和释放也要消耗资源),如果发生线程安全问题,就重新来过,这就是乐观锁;在线程特别多的情况下,发生线程安全的概率很大,重新来过花费的代价反而更大,就用上一种方法,直接加锁。</li> <li>此外,还可以通过原子类来保证共享变量的内存安全,即线程安全。 <h2>总结</h2></li> <li> <p>前两种属于隔离法,一个是位置隔离(数据只能自己访问,其它线程不能访问),一个是数据隔离(每个线程都有一份数据,各自访问各自的数据,互不干扰)。</p> </li> <li> <p>然后两种是标记法,一个是只读标记,一个是加锁标记。</p> </li> <li>第五种一种是大胆法,先来赌一把试试,若不行从头再来。</li> </ul>

页面列表

ITEM_HTML