目录
锁对象为Class,说明相同Class模板下的对象会线程同步
synchronized关键字是用来线程同步的,他可以写在方法声明的访问权限修饰符之前或之后,在方法声明添加了synchronized关键字代表,相同对象多个线程调用这个方法不再是线程的并发运行方式,而是以串行的运行方式
还可以以synchronized块来修饰需要线程同步的代码,因为若将一个大的方法声明为synchronized会大大影响效率,而synchronized块可以精确的控制具体需要线程同步的代码
语法:
synchronized块:synchronized(锁对象){同步代码}
synchronized线程同步的作用:可阻止并发更新一个共享资源,将运行方式改为串行
下面我们来讲讲synchronized的锁对象可以有谁:
1、使用this作为线程对象锁:
使用this作为线程对象锁的作用:当相同对象多个线程去调用此线程同步方法,就会线程互斥。我们来通过代码来看看:
我们创建一个账户类,提供通过账户取款的方法
然后创建取款线程
通过主线程去开启取款线程
按理来说应该输出:
爸取款200元,一拳超人账户余额300元
妈取款200元,一拳超人账户余额100元,此时我们来看输出
哎此时我们可以看到妈先取了钱但是账户余额只有100,爸后取的钱账户余额也只有100元,这就是线程没有同步的问题,当多个线程通过同一个对象去更改共享资源时,此时就需要用到线程同步
此时我们可以在取款的方法中添加synchronized关键字,是方法线程同步,当synchronized修饰的是方法时,此时对象锁就是this,而this指向的就是调用这个方法的对象,那么就把this锁住了,当这个线程运行完之后,才会释放锁给别的线程使用
当synchronized修饰的是方法时,此时对象锁就是this,相同对象调用此方法就会串行调用
2、使用字符串作为线程对象锁
使用字符串作为线程对象锁就是当所有对象访问这个方法的时候都需要排队,等先进去的出来了,然后释放锁再给排队的一个一个进
我们还是通过上面的代码讲解:
在主线程创建两个账户类,然后新建取款线程对这两个对象分别进行取款
如果是以上面的代码来看,相同对象就会排斥,那么这个是不同对象,那么就不会排斥,这两个账户分别取款200元
而如果将synchronized块的锁对象改为字符串对象那么所有调用此方法的对象都会同步
通过代码来理解,此时我们在账户类添加一个存钱方法
我们再添加一个存钱线程
然后我们通过主线程创建两个账户,并且创建存钱线程然后启用
此时不再是线程并发的状态,而是线程串行的状态,只有此对象存钱完了,别的对象才能存钱
3、使用Class作为线程对象锁
使用class作为线程对象锁就是同一class模板下的对象线程同步
我们将synchronized的锁对象改为Account.class,就说明这个方法在同一class模板下的对象调用此方法会线程同步
输出结果:
总结:
锁对象为this,说明相同对象多线程调用此方法会线程同步
锁对象为字符串,说明所有对象多线程调用此方法会线程同步
锁对象为Class,说明相同Class模板下的对象会线程同步