在Java中,synchronized
是一个关键字,用于创建一个原子操作,即一次只允许一个线程执行的操作。synchronized
可以用于方法或代码块,以确保线程安全,防止多个线程同时访问共享资源而导致数据不一致的问题。
同步方法
当synchronized
用于方法时,整个方法都会被同步。如果一个实例方法被声明为synchronized
,那么每个对象的实例级别的锁(即对象的引用)将保证同一时间只有一个线程能够执行该方法。
public synchronized void myMethod() {
// 只有获得当前对象锁的线程可以执行这里的代码
}
如果synchronized
用于静态方法,那么锁定的是类的Class对象。这意味着同一时间只有一个线程可以执行该类的任何一个同步静态方法。
public static synchronized void myStaticMethod() {
// 只有获得当前类锁的线程可以执行这里的代码
}
同步代码块
synchronized
也可以用于代码块,这时我们可以选择性地同步代码的一部分,而不是整个方法。这样可以减少不必要的等待时间,提高效率。
public void myMethod() {
Object lock = new Object(); // 锁对象
synchronized (lock) {
// 只有获得lock对象锁的线程可以执行这里的代码
}
}
在代码块中,我们可以指定一个锁对象,任何线程要执行这个代码块,都必须先获得这个锁对象的锁。
锁的获取和释放
当一个线程进入同步方法或同步代码块时,它会自动获取锁。当线程执行完同步方法或代码块后,锁会被自动释放,其他线程可以获取这个锁。
重入锁
synchronized
在Java中是可重入的,这意味着同一个线程可以多次获取同一个锁。例如,如果一个线程已经获取了某个对象的锁并进入了同步块,那么这个线程可以再次进入该对象的另一个同步方法或同步块,而不会被自己阻塞。
公平性
synchronized
锁的获取是不公平的,即没有固定的顺序。线程获取锁的顺序取决于操作系统的调度,这可能会导致某些线程长时间等待。
总结
synchronized
是Java中实现线程同步的基本机制之一。通过使用synchronized
,我们可以确保共享资源在同一时间只被一个线程访问,从而避免并发问题。然而,过度使用synchronized
可能会导致性能问题,如死锁和线程饥饿。因此,在设计多线程程序时,应该仔细考虑同步的范围和时间,以及是否有其他并发工具(如java.util.concurrent
包中的类)可以更有效地解决线程安全问题。