synchronized关键字

为什么要使用synchronized关键字

并发编程是为了提高程序的执行速度,在宏观上使得多个任务同时执行,则需要启动多个线程,但事实启动多个线程之后多个线程为了抢夺同一块资源,如果没有任何的同步操作,就会发生冲突,因为无法保证每个线程的执行满足并发编程的三大特性,原子性、可见性、有序性,所以就无法控制最终结果,造成线程不安全。
所以synchronized关键字提供一种排他机制,在同一时间内去操作synchornized封装的代码块或者方法,从而满足并发编程的3大特性,使得程序正确运行。

synchronized用法

方式1:同步方法
使用synchronize修饰的方法,就叫做同步方法。保证了A线程执行该方法时,其他线程只能在方法外等着

修饰一般方法
public synchronized void 方法名(){
//方法体
}
修饰静态方法
public synchronized static void 方法名(){
//方法体
}

方式2:同步代码块
注意:在任何时候最多允许一个线程拥有同步锁。谁拿到锁谁就进入代码块,其他的线程只能在外面等着。

private final Object lock = new Object();//lock为同步锁
public void func(){
	synchronized(同步锁){  
 	// 需要同步操作的代码
	}
}

不要使用synchronize修饰Run方法,修饰之后某一个线程执行完了所有的功能。就好比是对各线程出现串行。
解决方式:吧需要同步操作的代码定义在一个新的方法中,并且该方法使用synchronize修饰,再在run方法中调用该方法即可。

底层原理

)同步方法
常量池中多了ACC_SYNCHRONIZED标识符,标识当前的方法是一个同步方法,当方法被调用,调用指令会检查方法ACC_SYNCHRONIZED标识符是否被设置,如果设置,执行线程会先去获取monitor,获取成功之后才会去执行方法题,方法体执行完成之后或释放monitor。
2)同步代码块:
monitorenter
每一个对象都与一个monitor相关联,一个monitor的lock只能被一个线程在同一时间所拥有,在一个线程尝试获取monitor的使用会发生以下事情:
a.如果monitor的entry count为0,意味monitor的lock还没有被获取,某个线程获取之后会对entry count+1,从此该线程就是这个monitor的所有者了
b.如果一个已经拥有该monitor使用权的线程再次进入,会导致monitor的entry count+1(可重入锁)
c.如果monitor已经被其他线程所拥有,其他线程尝试获取该monitor的额所有权时,会被陷入阻塞,直到monitor的entry count为0,才能再次尝试去获取。
monitorexit
释放对monitor的使用权,要释放对某个对象的monitor的使用权前提是首先获取该monintor的 所有权,将monitor的entry count-1,如果entry count为0,那就表示该线程不再拥有该monitor的使用

synchornized的使用场景

  • 1、两个线程同时访问同一个对象的同步方法 安全
  • 2、两个线程同时访问两个对象的同步方法 不安全 test1.func1() test2.func1()
  • 3、两个线程同时访问(一个或两个)对象的静态同步方法 安全
  • 4、两个线程分别同时访问(一个或两个)对象的同步方法和非同步方法 不安全
  • 5、两个线程访问同一个对象中的同步方法,同步方法又调用另外一个非同步方法 不安全
  • 6、两个线程同时访问同一个对象的不同的同步方法 安全
  • 7、两个线程同时访问静态synchronized和非静态synchornized方法 不安全
  • 8、同步方法抛出异常,JVM会自动释放锁

synchronize的好与坏:

好处:保证了多线程并发访问时的同步操作,避免了线程的安全性问题。
缺点:使用synchronize的方法或代码块 的性能比不用要低一些。
建议:尽量减少synchronize的作用域。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值