要保证线程安全,并不是一定就要进行同步,两者没有因果关系。同步只是保证共享数据争用 时的正确性的手段,如果一个方法本来就不涉及共享数据,那它自然就无需任何同步操作去保 证正确性,因此会有一些代码天生就是线程安全的。
1、 可重入代码
可重入代码(ReentrantCode)也称为纯代码(Pure Code),可以在代码执行的任何时刻中断 它,转而去执行另外一段代码,而在控制权返回后,原来的程序不会出现任何错误。所有的可 重入代码都是线程安全的,但是并非所有的线程安全的代码都是可重入的。
可重入代码的特点是不依赖存储在堆上的数据和公用的系统资源、用到的状态量都是由参数中 传入、不调用非可重入的方法等。
类比:synchronized拥有锁重入的功能,也就是在使用synchronized时,当一个线程得到一 个对象锁后,再次请求此对象锁时时可以再次得到该对象的锁
2、 线程本地存储
如果一段代码中所需的数据必须与其他代码共享,那就看看这些共享数据的代码是否能保证在 同一个线程中执行?如果能保证,我们就可以把共享数据的可见范围限制在同一个线程之内。 这样无需同步也能保证线程之间不出现数据的争用问题。
符合这种特点的应用并不少见,大部分使用消费队列的架构模式(如“生产者-消费者”模式) 都会将产品的消费过程尽量在一个线程中消费完。其中最重要的一个应用实例就是经典的Web 交互模型中的"一个请求对应一个服务器线程(Thread-per-Request)"的处理方式,这种处 理方式的广泛应用使得很多Web服务器应用都可以使用线程本地存储来解决线程安全问题。
出现线程安全问题的原因一般都是三个原因:
1、 线程切换带来的原子性问题解决办法:使用多线程之间同步synchronized或使用锁 (lock)。
2、 缓存导致的可见性问题解决办法:synchronized, volatile, LOCK,可以解决可见性问 题
3、 编译优化带来的有序性问题解决办法:Happens-Before规则可以解决有序性问题

Was this helpful?

0 / 0

发表回复 0

Your email address will not be published.