在我们的多线程中,我们还需要去了解一个很重要的关键字,那就是synchronized关键字,那我们就来具体聊一聊为什么要创建这样一个关键字吧!
synchronized关键字的意义
在我们的日常开发当中,使用多线程都是使用并发编程,可能会出现线程安全问题,那这个时候我们就需要用到synchronized来解决。比如说在多线程环境下,如果多个线程同时访问和修改共享的数据或资源,可能会导致竞态条件,从而产生不可预测的结果或数据错误。使用 synchronized
可以保证同一时刻只有一个线程可以进入同步代码块或方法,避免竞态条件的发生。还有一种情况就是我们的线程会将数据变更刷新到内存当中,但我们的将数据录入到内存当中的这段时间会有其他线程也进数据的读取,我们录入的速度没有其他线程的读取速度快,就会造成数据可见性的问题,这个时候就会有线程安全问题,关于线程安全,我们以后会有更详细的解释。
synchronized的特性
互斥
刷新内存
可重入
可重入特性的原理:
同一个线程可以多次获取同一把锁:当一个线程持有某个锁时,如果这个线程再次试图获取同一把锁,它会成功获取,而不会被自己持有的锁所阻塞。这种情况下,锁计数器会递增。
锁持有计数器:每个锁关联一个持有计数器(lock count),用于记录某个线程获取该锁的次数。当线程首次获取锁时,计数器从0变为1。每当同一个线程再次获取该锁时,计数器递增。只有当计数器归零时,锁才会被完全释放。
释放锁的条件:锁只有在持有线程完全释放它时,才能被其他线程获取。这意味着同一个线程在持有锁期间,可以多次进入同步块或方法,而不会被自己的锁持有所阻塞。
public class ReentrantExample {
public synchronized void outer() {
inner();
// 外部同步方法可以调用内部同步方法
}
public synchronized void inner() {
// 内部同步方法
}
}
在这个示例中,outer()
方法和 inner()
方法都是同步方法,并且它们都使用了 synchronized
关键字来保证线程安全。如果一个线程已经持有了 ReentrantExample
对象的锁(通过调用 outer()
方法),那么它可以继续调用 inner()
方法,而无需重新获取锁,因为它已经持有了该锁的计数。
synchronized 使用示例
public class SynchronizedDemo {
public synchronized void methond() {
}
}
public class SynchronizedDemo {
public synchronized static void method() {
}
}
// 锁当前对象
public class SynchronizedDemo {
public void method() {
synchronized (this) {
}
}
}
// 锁类对象
public class SynchronizedDemo {
public void method() {
synchronized (SynchronizedDemo.class) {
}
}
}
小结
总结来说,synchronized
关键字是Java中最基本且简单的线程同步机制,通过对对象的锁定来保证多线程访问的安全性,但在某些情况下可能需要考虑其对性能的影响以及可替代的更灵活的锁实现方式。