问题历史:
自Java问世以来,开发者面临着竞争访问共享资源的问题。为了解决这个问题,引入了高级同步原语,最重要的是关键修饰符synchronized。
问题:
在多线程应用中,如果没有同步,共享资源可能会被破坏:会出现数据竞争,导致对象状态变得不可预测。
解决方案:
synchronized允许对方法或代码块进行监视,从而确保在任何时刻只有一个线程可以访问临界区。线程同步可以在方法级别或块级别实现。
对象锁定示例:
public class Counter { private int count = 0; public synchronized void increment() { count++; } public int getCount() { return count; } }
也可以同步代码块:
public void safeIncrement() { synchronized(this) { count++; } }
关键特点:
synchronized方法与synchronized块有什么区别?
synchronized方法会锁定当前对象(this)或类(如果是静态方法)。块允许同步代码的特定部分,并选择任何对象来进行锁定。
两个不同线程能否同时进入同一对象的两个不同synchronized方法?
不可以,如果方法是在同一个监视器(this)上同步的。如果使用不同的监视器,则可以。
synchronized修饰符是否会影响线程之间变量的可见性?
是的,进入synchronized块会清除线程缓存并更新变量值(发生在之前的关系)。
开发者在实例对象上同步类的静态方法,这在通过不同实例使用时不能保证正确性。
优点:
缺点:
所有使用共享资源的方法都在同一个对象监视器上同步,临界区的范围最小。
优点:
缺点: