什么时候用synchronized
解决安全问题的方式:
java中提供了一个同步机制:
解决原理:让多条操作共享数据的代码在某一个时间段,被一个线程执行完,在执行过程中,其它线程不可以参与执行
同步格式:
同步代码块:
synchronized(对象) //对象可以是任意对象,但是不能是匿名对象和匿名子类对象
{
需要同步的代码;
}
Synchronized关键字是确定同步区域,对象表示锁
只有持有锁的线程才可以进入到同步中,执行里面的代码。执行完毕后,线程走出同步(区域),同时释放锁
同步原理:
通过一个对象锁,将多条操作共享数据的代码语句进行了封装并加锁
只有持有这个锁的线程才可能进入同步中的去执行代码,在执行期间,即使其他线程获得了cpu的执行权,但是因为没有获取锁,所以线程只能在同步外面等,只有同步中的线程执行完同步中的代码,走出同步代码块时,线程才会释放这个锁。那么其他线程才有机会获取这个锁,并且只有一个线程获取到锁,进入到同步代码块中
sleep() :线程不会释放锁,但是会短暂失去cpu执行权和执行资格,睡眠时间一到,线程就重新获取执行资格
同步好处:
同步的出现解决了多线程的安全问题。
同步弊端:
因为多个线程每次都要判断这个锁,所以效率会降低
同步的前提:
1,必须是两个或者两个以上的线程才需要同步
2,必须要保证多个线程使用的是同一个锁,才可以实现多个线程被同步
如果加上同步安全问题依然存在,就按照这两个前提来排除问题
同步函数:
需求:有两个客户,往银行里存钱,每个每次存100,存3次
判断代码是否存在安全隐患
分析:
1,查看线程代码中是否有共享数据
2,这个共享数据有没有被多条语句所操作
发现:sum是共享数据,有两条语句在操作这个共享数据,如果这两条语句被多个线程分开执行
也就是一个线程没有执行完,其它线程就参与执行,就容易发生安全问题
解决办法:加入同步机制,将需要被一个线程一次执行完的代码存储到同步代码块中
同步代码块是用于封装代码,而函数也是用来封装代码的,所不同之处是同步带有锁机制
在函数上加上一个关键字synchronized修饰,那么这个函数就是同步函数,具备同步的特性,效果跟同步代码块是一样的
同步函数使用的到底是哪个锁?
同步函数使用的锁是this(当前本类对象)
同步函数和同步代码块的区别:
同步代码块使用的锁可以是任意对象
同步函数使用的锁是固定对象this(当前本类对象)
所以一般定义同步时,建议使用同步代码块,当然,如果对象可以使用this,
那么可以简化同步函数的形式