//开篇解释线程安全大概
什么是线程安全,指的就是,当多个线程访问同一个资源(这个资源很泛泛,有可能是一个对象的一个方法,也有可能是一个类的方法)时,相互之间不会产生影响,表现出正确的行为时,谓之线程安全。
//解释synchronize关键字的使用大概
synchronize关键字我们并不陌生,被synchronize关键字修饰的代码或者方法,会被有一把“同步锁”,只有获得同步锁的线程才能够执行同步代码,而未获得同步锁的线程会不停地尝试去获取同步锁,直到获得为止,当多个线程都在等待获取同一把同步锁时,就会出现锁竞争的现象,由CPU分配下一次获得锁的线程。在一个线程已经获取了一个对象的锁以后,如果当线程再次请求对象,还是可以获得该对象的锁。
//锁的作用范围
需要注意的是,synchronize修饰的锁,是对象锁(该对象指的是这段代码所属对象),并不是代表对这段代码上了锁。一个对象,只有一把锁,也就是说,当两个线程,对两个对象的同一synchronize修饰代码进行调用,相互之间是不影响的。而如果在方法上加上static关键字的话,上的锁便是类锁,此时,任何线程访问该方法,都只能等待同一把锁。同样的,如果未获得该对象的锁,将无法访问该对象所有的同步代码,所以,并不是说一个对象中的同一段synchronize修饰方法,作为共享资源,而是同一个对象中的所有synchronize修饰内容。就好比,一个对象开了一个房间,锁着的是synchronize修饰的资源,一旦知道自己需要调用的方法是synchronize修饰过的,就知道他一定在对象开的那个房间内,径直走到房间去,如果有锁,直接拿起锁上门,然后进去使用自己想要的方法,如果有人锁上了门,你就得等,即使他在里面用的不是你想要的东西。(注:使用synchronize代码块的参数可以细化同步锁作用范围,this代表对象锁,class对象表示锁类,也可以锁其他对象,但是一旦参数发生变化,就会产生新的锁)
//解析类锁和对象锁的区别
再对上文深入解析:现在涉及到的问题在于,多个线程对“同一个资源”进行“争抢”,而在上对象锁时,如果多个线程访问的是不同对象,那么就不存在冲突,因为他们获取的是不同的锁(也就是不同的房间),而如果上的是类锁,无论这几个线程通过何种方式调用该段代码都只能等待同一把锁,因为众所周知,一个class文件只能实例化一个Class对象。
//同步的意义
synchronize,中文名为同步,回顾一下同步和异步的区别,同步指的是在使用“共享”资源时,不同的线程需要相互等待,异步指的是,线程之间相互不受影响,各做各的事,如果不存在需要共享的资源,那就不需要同步了。
//进一步讲解线程安全
上文讲了那么多同步的使用,同步的目的是什么呢?是为了正文题目第一句,线程安全。
//线程安全的特性以及原子性
线程安全的两个最重要的特性:原子性,可见性。同步便是为了实现原子性。
简单的讲解一个例子(脏读):当一个对象有两个方法,分别为取值,和设值,如果只对设值方法进行加锁,或者干脆不加锁,会怎么样呢?在一个线程需要花一段时间设置值的时候,另外一个线程进入,读到了还未被设置好的值,出现“脏读”。所以我们需要将两个方法前都加上关键字,也就是,将他们关进同一个房间,保证原子性,这就是同步的意义。(拓展:Oracle数据库的一致性读,undo)
本文详细阐述了线程安全的概念及其重要性,探讨了synchronize关键字如何确保代码的原子性和可见性,防止多线程环境下的数据不一致问题。
1189

被折叠的 条评论
为什么被折叠?



