在java 开发中,我们在使用synchronized关键字对同步数据进行加锁时,有两种写法,一是同步方法,另一种时同步方法块。
代码如下:
/**
* @author Evan Walker
* @version 1.0
* @desc 昂炎数据 https://www.ayshuju.com/home
* @date 2023/03/23 22:22:50
*/
public class SynchronizeDemo {
Object lock = new Object();
/**
* 第一种,锁住整个静态method 类锁(同步方法)
*/
public static synchronized void synchronizedMethodA() {
//业务代码
}
/**
* 第一种相当于用类对象锁住代码块 类锁(同步代码块)
*/
public static void synchronizedBlockA() {
synchronized (SynchronizeDemo.class) {
//业务代码
}
}
/**
* 第二种,使用一个互斥对象锁住代码块;它可以这么理解,多个线程想访问互斥代码块,必须拿到mutex对象的锁。
* 然后,后面的所有类型都可以用第一种类型来解释(同步代码块)
*/
public void synchronizedBlockB() {
synchronized (lock) {
// 业务代码
}
}
/**
* 第三种,锁住整个非静态method (同步方法)
*/
public synchronized void synchronizedMethodC() {
//业务代码
}
/**
* 第三种相当于用this对象来锁住方法(同步代码块)
*/
public void synchronizedBlockC() {
synchronized (this) {
//业务代码
}
}
}
上述代码描述了几种同步方法,和同步代码块的写法。
同步方法与同步块的区别
同步方法:同步方法直接在方法上加 synchronized 实现加锁。
同步方法块:同步代码块则在方法内部加锁,在起方法内部实现synchronized关键字。
同步方法与同步块那个是更好的选择?
同步代码块是更好的选择
因为它不会锁住整个对象(当然你也可以让它锁住整个对象),意味着同步块之外的代码是异步执行的,效率会更高。同步方法会锁住整个对象,哪怕这个类中有对各不相关联的同步块,这通常会导致他们停止执行并需要等待获取这个对象上的锁。
同步代码块更要符合开放调用原则,只在需要锁住的代码块锁住相应的对象,这样从侧面来说可以避免死锁。
请知道这样一条原则,同步的范围越小越好。
但也有例外:Java锁粗化
虽说同步的范围越少越好,但在 Java 虚拟机中存在着一种叫做锁粗化的优化方法,这种方法是把同步范围变大。比方说 StringBuffer ,它是一个线程安全的类,自然最常用的 append() 方法是一个同步方法,写代码的时会反复 append 字符串,这意味着要进行反复的加锁 -> 解锁,这对性能不利,这意味着 Java 虚拟机在这条线程上要反复地在内核态和用户态之间进行切换,因此 Java 虚拟机会将多次 append 方法调用的代码进行一个锁粗化的操作,将多次的 append 的操作扩展到 append 方法的头尾,变成一个大的同步块,这样就减少了加锁 --> 解锁的次数,有效地提升了代码执行的效率。
更多消息资讯,请访问昂炎数据(https://www.ayshuju.com/home)